Changeset 267 for trunk


Ignore:
Timestamp:
Apr 14, 2019, 2:31:40 PM (6 years ago)
Author:
roby
Message:
 
Location:
trunk/client
Files:
65 edited

Legend:

Unmodified
Added
Removed
  • trunk/client/class/charts.php

    r265 r267  
    11<?php
    2 // charts.php v4.7
     2// charts.php v4.5
    33// ------------------------------------------------------------------------
    4 // Copyright (c) 2003-2007, maani.us
     4// Copyright (c) 2003-2006, maani.us
    55// ------------------------------------------------------------------------
    66// This file is part of "PHP/SWF Charts"
     
    1111
    1212//====================================
    13 function InsertChart( $flash_file, $library_path, $php_source, $width=400, $height=250, $bg_color="666666", $transparent=false, $license=null ){
    14        
     13function InsertChart( $flash_file, $library_path, $php_source, $width=470, $height=350, $bg_color="ffffff", $transparent=false, $license=null ){
     14       
    1515        $php_source=urlencode($php_source);
    1616        $library_path=urlencode($library_path);
    17         $protocol = (strtolower($_SERVER['HTTPS']) != 'on')? 'http': 'https';
     17        $x=$_SESSION['max'];
     18        $u=(strpos ($flash_file,"?")==false)? "?" : ((substr($flash_file, -1)=="&")? "":"&");
    1819
    19         $html="<OBJECT classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='".$protocol."://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0' ";
    20         $html.="width='".$width."' height='".$height."' id='charts' />";
    21         $u=(strpos ($flash_file,"?")===false)? "?" : ((substr($flash_file, -1)==="&")? "":"&");
    22         $html.="<PARAM NAME='movie' VALUE='".$flash_file.$u."library_path=".$library_path."&stage_width=".$width."&stage_height=".$height."&php_source=".$php_source;
    23         if($license!=null){$html.="&license=".$license;}
    24         $html.="' /> <PARAM NAME='quality' VALUE='high' /><param name='allowScriptAccess' value='sameDomain' /><PARAM NAME='bgcolor' VALUE='#".$bg_color."' /> ";
    25         if($transparent){$html.="<PARAM NAME='wmode' VALUE='transparent' /> ";}
    26         $html.="<EMBED src='".$flash_file.$u."library_path=".$library_path."&stage_width=".$width."&stage_height=".$height."&php_source=".$php_source;
    27         if($license!=null){$html.="&license=".$license;}
    28         $html.="' quality='high' bgcolor='#".$bg_color."' width='".$width."' height='".$height."' NAME='charts' allowScriptAccess='sameDomain' swLiveConnect='true' ";
    29         if($transparent){$html.="wmode=transparent ";} //use wmode=opaque to prevent printing on black
    30         $html.="TYPE='application/x-shockwave-flash' PLUGINSPAGE='".$protocol."://www.macromedia.com/go/getflashplayer'></EMBED></OBJECT>";
     20
     21        $html="<div style=\"text-align: right;\">";
     22        if (strstr($_SERVER['HTTP_USER_AGENT'],"MSIE")){
     23                $html.="<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0' ";
     24                $html.="width='".$width."' height='".$height."' id='charts$x'>";
     25                $u=(strpos ($flash_file,"?")==false)? "?" : ((substr($flash_file, -1)=="&")? "":"&");
     26                $html.="<param name='movie' value='".$flash_file.$u."library_path=".$library_path."&amp;php_source=".$php_source;
     27                if($license!=null){$html.="&amp;license=".$license;}
     28                $html.="'/> <param name='quality' value='high'/> <param name='bgcolor' value='#".$bg_color."'/> ";
     29                if($transparent){$html.="<param name='wmode' value='transparent'/> ";}
     30                $html.="</object>";
     31        }else{
     32                $html.="<embed src=\"".$flash_file.$u."library_path=".$library_path."&amp;php_source=".$php_source;
     33                if($license!=null){$html.="&amp;license=".$license;}
     34                $html.="\" quality=high bgcolor=#".$bg_color." width=".$width." height=".$height." name='charts' align='right' swLiveConnect='true' ";
     35                if($transparent){$html.="wmode=transparent ";}
     36                $html.="type='application/x-shockwave-flash' pluginspage='http://www.macromedia.com/go/getflashplayer'></embed>";
     37        }
     38        $html.="</div>";
     39
    3140        return $html;
     41       
    3242       
    3343}
     
    3545//====================================
    3646function SendChartData( $chart=array() ){
    37 
    38         //header("Content-Type: text/xml");
    39         //header("Cache-Control: cache, must-revalidate");
    40         //header("Pragma: public");
     47       
    4148       
    4249        $xml="<chart>\r\n";
     
    5461                                                for($i3=0;$i3<count($Keys3);$i3++){
    5562                                                        switch(true){
    56                                                                 case ($chart[$Keys1[$i1]][$Keys2[$i2]][$Keys3[$i3]]===null):
     63                                                                case ($chart[$Keys1[$i1]][$Keys2[$i2]][$Keys3[$i3]]==null):
    5764                                                                $xml.="\t\t\t<null/>\r\n";
    5865                                                                break;
     
    7481                                                $count=0;
    7582                                                for($i3=0;$i3<count($Keys3);$i3++){
    76                                                         if($chart[$Keys1[$i1]][$Keys2[$i2]][$Keys3[$i3]]===null){$xml.="\t\t\t<null/>\r\n";}
     83                                                        if($chart[$Keys1[$i1]][$Keys2[$i2]][$Keys3[$i3]]==null){$xml.="\t\t\t<null/>\r\n";}
    7784                                                        else{$xml.="\t\t\t<string>".$chart[$Keys1[$i1]][$Keys2[$i2]][$Keys3[$i3]]."</string>\r\n";}
    7885                                                }
     
    8491                                                $count=0;
    8592                                                for($i3=0;$i3<count($Keys3);$i3++){
    86                                                         if($chart[$Keys1[$i1]][$Keys2[$i2]][$Keys3[$i3]]===null){$xml.="\t\t\t<null/>\r\n";}
     93                                                        if($chart[$Keys1[$i1]][$Keys2[$i2]][$Keys3[$i3]]==null){$xml.="\t\t\t<null/>\r\n";}
    8794                                                        else{$xml.="\t\t\t<string>".$chart[$Keys1[$i1]][$Keys2[$i2]][$Keys3[$i3]]."</string>\r\n";}
    8895                                                }
     
    118125                                        $xml.="\t<".$Keys1[$i1].">\r\n";
    119126                                        for($i2=0;$i2<count($Keys2);$i2++){
    120                                                 if($chart[$Keys1[$i1]][$Keys2[$i2]]===null){$xml.="\t\t<null/>\r\n";}
     127                                                if($chart[$Keys1[$i1]][$Keys2[$i2]]==null){$xml.="\t\t<null/>\r\n";}
    121128                                                else{$xml.="\t\t<value>".$chart[$Keys1[$i1]][$Keys2[$i2]]."</value>\r\n";}
    122129                                        }
     
    135142        }
    136143        $xml.="</chart>\r\n";
    137         echo $xml;
     144/*        // stampa su file by Linuxap
     145        mt_srand ((double)microtime()*1000000);
     146        $maxran = 1000000;
     147        $random_num = mt_rand(0, $maxran);
     148        $fileout="./temp/$random_num";
     149        $fp = fopen($fileout,"w");
     150        fwrite($fp,$xml);
     151        fclose($fp);
     152*/
     153        //echo $xml;
     154//MODIFICHE PER TOGLIERE FILETEMP
     155        return $xml; //return $fileout;
    138156}
    139157//====================================
  • trunk/client/modules/Elezioni/grafici.php

    r265 r267  
    77/* info@eleonline.it  luciano@aniene.net rgigli@libero.it               */
    88/************************************************************************/
    9 define('MODULE_FILE');
     9
    1010if (!defined('MODULE_FILE')) {
    11 #    die ("You can't access this file directly...");
     11    die ("You can't access this file directly...");
    1212}
    1313
     
    164164        $_GET : $_POST;
    165165if (isset($param['anim'])) $anim=intval($param['anim']); else $anim='';
     166#$anim=1;
    166167if ($siteistat==$id_comune) $logo="$siteistat"; else $logo=''; // logo per il  comune
    167168$logo=verificasimbolo(); // carica_logo da funzioni.php
     
    604605                echo "</td></tr></table><table><tr><td>";
    605606                # grafico flash
    606                 if($flash=='1') flash_torta($gruppos,$pre,40,145);
     607#               if($flash=='1') flash_torta($gruppos,$pre,40,145);
     608                                $uno='';
     609                                foreach($gruppos as $k=>$v) $uno.="- $v";
     610                                $due='due:';
     611                                foreach($pre as $k=>$v) $due.="- $v";
     612                                include("flash_torta($uno,$due,20,70)");
    607613                echo "</td></tr></table>";
    608614               
     
    674680
    675681                                if($flash=='1')flash_torta($gruppos,$pre,20,70);
    676                                
     682
    677683
    678684
     
    796802               
    797803                $chart[ 'chart_data' ] = array ($gruppos, $pre);
    798                 //$chart[ 'chart_data' ] = array ( array ("","Ciao", "Bella"), array ( "",40, 60));
     804                $chart[ 'chart_data' ] = array ( array ("","Ciao", "Bella"), array ( "",40, 60));
    799805                $chart[ 'chart_grid_h' ] = array ( 'thickness'=>0 );
    800806                $chart[ 'chart_pref' ] = array ( 'rotation_x'=>60 );
  • trunk/client/modules/Elezioni/grafici/gd_image.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        GD_IMAGE.INC.PHP
    4 // Description: PHP Graph Plotting library. Low level image drawing routines
    5 // Created:     2001-01-08, refactored 2008-03-29
    6 // Ver:         $Id: gd_image.inc.php 1922 2010-01-11 11:42:50Z ljp $
     3// File:        GD_IMAGE.INC.PHP
     4// Description: PHP Graph Plotting library. Low level image drawing routines
     5// Created:     2001-01-08, refactored 2008-03-29
     6// Ver:         $Id$
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
    11 require_once 'jpgraph_rgb.inc.php';
    12 require_once 'jpgraph_ttf.inc.php';
    13 require_once 'imageSmoothArc.php';
    14 require_once 'jpgraph_errhandler.inc.php';
    15 
    16 // Line styles
    17 define('LINESTYLE_SOLID',1);
    18 define('LINESTYLE_DOTTED',2);
    19 define('LINESTYLE_DASHED',3);
    20 define('LINESTYLE_LONGDASH',4);
    21 
    22 // The DEFAULT_GFORMAT sets the default graphic encoding format, i.e.
    23 // PNG, JPG or GIF depending on what is installed on the target system
    24 // in that order.
    25 if( !DEFINED("DEFAULT_GFORMAT") ) {
    26     define("DEFAULT_GFORMAT","auto");
    27 }
    28 
    29 //========================================================================
     11       
     12//===================================================
    3013// CLASS Image
    31 // Description: The very coor image drawing class that encapsulates all
    32 //              calls to the GD library
    33 //              Note: The class used by the library is the decendant
    34 //              class RotImage which extends the Image class with transparent
    35 //              rotation.
    36 //=========================================================================
     14// Description: Wrapper class with some goodies to form the
     15// Interface to low level image drawing routines.
     16//===================================================
    3717class Image {
     18    public $left_margin=30,$right_margin=30,$top_margin=20,$bottom_margin=30;
    3819    public $img=null;
     20    public $plotwidth=0,$plotheight=0;
     21    public $width=0, $height=0;
    3922    public $rgb=null;
     23    public $current_color,$current_color_name;
     24    public $line_weight=1, $line_style=LINESTYLE_SOLID;
    4025    public $img_format;
    4126    public $ttf=null;
    42     public $line_style=LINESTYLE_SOLID;
    43     public $current_color,$current_color_name;
    44     public $original_width=0, $original_height=0;
    45     public $plotwidth=0,$plotheight=0;
    46 
    47     // for __get, __set
    48     private $_left_margin=30,$_right_margin=30,$_top_margin=20,$_bottom_margin=30;
    49     //private $_plotwidth=0,$_plotheight=0;
    50     private $_width=0, $_height=0;
    51     private $_line_weight=1;
    52 
    5327    protected $expired=true;
    5428    protected $lastx=0, $lasty=0;
    5529    protected $obs_list=array();
    56     protected $font_size=12,$font_family=FF_DEFAULT, $font_style=FS_NORMAL;
     30    protected $font_size=12,$font_family=FF_FONT1, $font_style=FS_NORMAL;
    5731    protected $font_file='';
    5832    protected $text_halign="left",$text_valign="bottom";
     
    6337    protected $langconv = null ;
    6438    protected $iInterlace=false;
    65     protected $bbox_cache = array(); // STore the last found tetx bounding box
    66     protected $ff_font0;
    67     protected $ff_font0_bold;
    68     protected $ff_font1;
    69     protected $ff_font1_bold;
    70     protected $ff_font2;
    71     protected $ff_font2_bold;
    72 
    73 
    7439    //---------------
    7540    // CONSTRUCTOR
    76     function __construct($aWidth=0,$aHeight=0,$aFormat=DEFAULT_GFORMAT,$aSetAutoMargin=true) {
    77 
    78         $this->original_width  = $aWidth;
    79         $this->original_height = $aHeight;
    80         $this->CreateImgCanvas($aWidth, $aHeight);
    81 
    82         if( $aSetAutoMargin ) {
    83             $this->SetAutoMargin();
    84         }
    85 
    86         if( !$this->SetImgFormat($aFormat) ) {
    87             JpGraphError::RaiseL(25081,$aFormat);//("JpGraph: Selected graphic format is either not supported or unknown [$aFormat]");
    88         }
    89         $this->ttf = new TTF();
    90         $this->langconv = new LanguageConv();
    91 
    92         $this->ff_font0 =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT0.gdf");
    93         $this->ff_font1 =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT1.gdf");
    94         $this->ff_font2 =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT2.gdf");
    95         $this->ff_font1_bold =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT1-Bold.gdf");
    96         $this->ff_font2_bold =  imageloadfont(dirname(__FILE__) . "/fonts/FF_FONT2-Bold.gdf");
     41    function Image($aWidth,$aHeight,$aFormat=DEFAULT_GFORMAT,$aSetAutoMargin=true) {
     42        $this->CreateImgCanvas($aWidth,$aHeight);
     43        if( $aSetAutoMargin )
     44            $this->SetAutoMargin();             
     45
     46        if( !$this->SetImgFormat($aFormat) ) {
     47            JpGraphError::RaiseL(25081,$aFormat);//("JpGraph: Selected graphic format is either not supported or unknown [$aFormat]");
     48        }
     49        $this->ttf = new TTF();
     50        $this->langconv = new LanguageConv();
    9751    }
    9852
    9953    // Enable interlacing in images
    10054    function SetInterlace($aFlg=true) {
    101         $this->iInterlace=$aFlg;
     55        $this->iInterlace=$aFlg;
    10256    }
    10357
    10458    // Should we use anti-aliasing. Note: This really slows down graphics!
    10559    function SetAntiAliasing($aFlg=true) {
    106         $this->use_anti_aliasing = $aFlg;
    107         if( function_exists('imageantialias') ) {
    108             imageantialias($this->img,$aFlg);
    109         }
    110         else {
    111             JpGraphError::RaiseL(25128);//('The function imageantialias() is not available in your PHP installation. Use the GD version that comes with PHP and not the standalone version.')
    112         }
    113     }
    114 
    115     function GetAntiAliasing() {
    116         return $this->use_anti_aliasing ;
     60        $this->use_anti_aliasing = $aFlg;
     61        if( function_exists('imageantialias') ) {
     62            imageantialias($this->img,$aFlg);
     63        }
     64        else {
     65            JpGraphError::RaiseL(25128);//('The function imageantialias() is not available in your PHP installation. Use the GD version that comes with PHP and not the standalone version.')
     66        }
    11767    }
    11868
    11969    function CreateRawCanvas($aWidth=0,$aHeight=0) {
    120 
    121         $aWidth  *= SUPERSAMPLING_SCALE;
    122         $aHeight *= SUPERSAMPLING_SCALE;
    123 
    124         if( $aWidth <= 1 || $aHeight <= 1 ) {
    125             JpGraphError::RaiseL(25082,$aWidth,$aHeight);//("Illegal sizes specified for width or height when creating an image, (width=$aWidth, height=$aHeight)");
    126         }
    127 
    128         $this->img = @imagecreatetruecolor($aWidth, $aHeight);
    129         if( $this->img < 1 ) {
    130             JpGraphError::RaiseL(25126);
    131             //die("Can't create truecolor image. Check that you really have GD2 library installed.");
    132         }
    133         $this->SetAlphaBlending();
    134 
    135         if( $this->iInterlace ) {
    136             imageinterlace($this->img,1);
    137         }
    138         if( $this->rgb != null ) {
    139             $this->rgb->img = $this->img ;
    140         }
    141         else {
    142             $this->rgb = new RGB($this->img);
    143         }
     70        if( $aWidth <= 1 || $aHeight <= 1 ) {
     71            JpGraphError::RaiseL(25082,$aWidth,$aHeight);//("Illegal sizes specified for width or height when creating an image, (width=$aWidth, height=$aHeight)");
     72        }
     73
     74        if( USE_TRUECOLOR ) {
     75            $this->img = @imagecreatetruecolor($aWidth, $aHeight);
     76            if( $this->img < 1 ) {
     77                JpGraphError::RaiseL(25126);
     78                //die("Can't create truecolor image. Check that you really have GD2 library installed.");
     79            }
     80            $this->SetAlphaBlending();
     81        } else {
     82            $this->img = @imagecreate($aWidth, $aHeight);       
     83            if( $this->img < 1 ) {
     84                JpGraphError::RaiseL(25126);
     85                //die("<b>JpGraph Error:</b> Can't create image. Check that you really have the GD library installed.");
     86            }
     87        }
     88
     89        if( $this->iInterlace ) {
     90            imageinterlace($this->img,1);
     91        }
     92        if( $this->rgb != null )
     93            $this->rgb->img = $this->img ;
     94        else
     95            $this->rgb = new RGB($this->img);                           
    14496    }
    14597
    14698    function CloneCanvasH() {
    147         $oldimage = $this->img;
    148         $this->CreateRawCanvas($this->width,$this->height);
    149         imagecopy($this->img,$oldimage,0,0,0,0,$this->width,$this->height);
    150         return $oldimage;
    151     }
    152 
     99        $oldimage = $this->img;
     100        $this->CreateRawCanvas($this->width,$this->height);
     101        imagecopy($this->img,$oldimage,0,0,0,0,$this->width,$this->height);
     102        return $oldimage;
     103    }
     104   
    153105    function CreateImgCanvas($aWidth=0,$aHeight=0) {
    154106
    155         $old = array($this->img,$this->width,$this->height);
    156 
    157         $aWidth = round($aWidth);
    158         $aHeight = round($aHeight);
    159 
    160         $this->width=$aWidth;
    161         $this->height=$aHeight;
    162 
    163 
    164         if( $aWidth==0 || $aHeight==0 ) {
    165             // We will set the final size later.
    166             // Note: The size must be specified before any other
    167             // img routines that stroke anything are called.
    168             $this->img = null;
    169             $this->rgb = null;
    170             return $old;
    171         }
    172 
    173         $this->CreateRawCanvas($aWidth,$aHeight);
    174         // Set canvas color (will also be the background color for a
    175         // a pallett image
    176         $this->SetColor($this->canvascolor);
    177         $this->FilledRectangle(0,0,$this->width-1,$this->height-1);
    178 
    179         return $old ;
     107        $old = array($this->img,$this->width,$this->height);
     108       
     109        $aWidth = round($aWidth);
     110        $aHeight = round($aHeight);
     111
     112        $this->width=$aWidth;
     113        $this->height=$aHeight;         
     114
     115       
     116        if( $aWidth==0 || $aHeight==0 ) {
     117            // We will set the final size later.
     118            // Note: The size must be specified before any other
     119            // img routines that stroke anything are called.
     120            $this->img = null;
     121            $this->rgb = null;
     122            return $old;
     123        }
     124       
     125        $this->CreateRawCanvas($aWidth,$aHeight);
     126        // Set canvas color (will also be the background color for a
     127        // a pallett image
     128        $this->SetColor($this->canvascolor);   
     129        $this->FilledRectangle(0,0,$aWidth,$aHeight);
     130
     131        return $old ;
    180132    }
    181133
    182134    function CopyCanvasH($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY,$aWidth,$aHeight,$aw=-1,$ah=-1) {
    183         if( $aw === -1 ) {
    184             $aw = $aWidth;
    185             $ah = $aHeight;
    186             $f = 'imagecopyresized';
    187         }
    188         else {
    189             $f = 'imagecopyresampled';
    190         }
    191         $f($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY, $aWidth,$aHeight,$aw,$ah);
     135        if( $aw === -1 ) {
     136            $aw = $aWidth;
     137            $ah = $aHeight;
     138            $f = 'imagecopyresized';
     139        }
     140        else {
     141            $f = 'imagecopyresampled';
     142        }
     143        $f($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY, $aWidth,$aHeight,$aw,$ah);
    192144    }
    193145
    194146    function Copy($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1) {
    195         $this->CopyCanvasH($this->img,$fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight);
     147        $this->CopyCanvasH($this->img,$fromImg,$toX,$toY,$fromX,$fromY,
     148                           $toWidth,$toHeight,$fromWidth,$fromHeight);
    196149    }
    197150
    198151    function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) {
    199         if( $aMix == 100 ) {
    200             $this->CopyCanvasH($this->img,$fromImg,
    201             $toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight);
    202         }
    203         else {
    204             if( ($fromWidth  != -1 && ($fromWidth != $toWidth)) || ($fromHeight != -1 && ($fromHeight != $fromHeight)) ) {
    205                 // Create a new canvas that will hold the re-scaled original from image
    206                 if( $toWidth <= 1 || $toHeight <= 1 ) {
    207                     JpGraphError::RaiseL(25083);//('Illegal image size when copying image. Size for copied to image is 1 pixel or less.');
    208                 }
    209 
    210                 $tmpimg = @imagecreatetruecolor($toWidth, $toHeight);
    211 
    212                 if( $tmpimg < 1 ) {
    213                     JpGraphError::RaiseL(25084);//('Failed to create temporary GD canvas. Out of memory ?');
    214                 }
    215                 $this->CopyCanvasH($tmpimg,$fromImg,0,0,0,0,
    216                 $toWidth,$toHeight,$fromWidth,$fromHeight);
    217                 $fromImg = $tmpimg;
    218             }
    219             imagecopymerge($this->img,$fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$aMix);
    220         }
     152        if( $aMix == 100 ) {
     153            $this->CopyCanvasH($this->img,$fromImg,
     154                               $toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight);
     155        }
     156        else {
     157            if( ($fromWidth  != -1 && ($fromWidth != $toWidth))  ||
     158                ($fromHeight != -1 && ($fromHeight != $fromHeight)) ) {
     159                // Create a new canvas that will hold the re-scaled original from image
     160                if( $toWidth <= 1 || $toHeight <= 1 ) {
     161                    JpGraphError::RaiseL(25083);//('Illegal image size when copying image. Size for copied to image is 1 pixel or less.');
     162                }
     163                if( USE_TRUECOLOR ) {
     164                    $tmpimg = @imagecreatetruecolor($toWidth, $toHeight);
     165                } else {
     166                    $tmpimg = @imagecreate($toWidth, $toHeight);       
     167                }           
     168                if( $tmpimg < 1 ) {
     169                    JpGraphError::RaiseL(25084);//('Failed to create temporary GD canvas. Out of memory ?');
     170                }
     171                $this->CopyCanvasH($tmpimg,$fromImg,0,0,0,0,
     172                                   $toWidth,$toHeight,$fromWidth,$fromHeight);
     173                $fromImg = $tmpimg;
     174            }
     175            imagecopymerge($this->img,$fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$aMix);
     176        }
    221177    }
    222178
    223179    static function GetWidth($aImg=null) {
    224         if( $aImg === null ) {
    225             $aImg = $this->img;
    226         }
    227         return imagesx($aImg);
     180        if( $aImg === null )
     181            $aImg = $this->img;
     182        return imagesx($aImg);
    228183    }
    229184
    230185    static function GetHeight($aImg=null) {
    231         if( $aImg === null ) {
    232             $aImg = $this->img;
    233         }
    234         return imagesy($aImg);
    235     }
    236 
     186        if( $aImg === null )
     187            $aImg = $this->img;
     188        return imagesy($aImg);
     189    }
     190   
    237191    static function CreateFromString($aStr) {
    238         $img = imagecreatefromstring($aStr);
    239         if( $img === false ) {
    240             JpGraphError::RaiseL(25085);
    241             //('An image can not be created from the supplied string. It is either in a format not supported or the string is representing an corrupt image.');
    242         }
    243         return $img;
     192        $img = imagecreatefromstring($aStr);
     193        if( $img === false ) {
     194            JpGraphError::RaiseL(25085);//('An image can not be created from the supplied string. It is either in a format not supported or the string is representing an corrupt image.');
     195        }
     196        return $img;
    244197    }
    245198
    246199    function SetCanvasH($aHdl) {
    247         $this->img = $aHdl;
    248         $this->rgb->img = $aHdl;
     200        $this->img = $aHdl;
     201        $this->rgb->img = $aHdl;
    249202    }
    250203
    251204    function SetCanvasColor($aColor) {
    252         $this->canvascolor = $aColor ;
     205        $this->canvascolor = $aColor ;
    253206    }
    254207
    255208    function SetAlphaBlending($aFlg=true) {
    256         ImageAlphaBlending($this->img,$aFlg);
    257     }
    258 
    259     function SetAutoMargin() {
    260         $min_bm=5;
    261         $lm = min(40,$this->width/7);
    262         $rm = min(20,$this->width/10);
    263         $tm = max(5,$this->height/7);
    264         $bm = max($min_bm,$this->height/6);
    265         $this->SetMargin($lm,$rm,$tm,$bm);
    266     }
    267 
     209        ImageAlphaBlending($this->img,$aFlg);
     210    }
     211
     212       
     213    function SetAutoMargin() { 
     214        GLOBAL $gJpgBrandTiming;
     215        $min_bm=5;
     216        /*
     217        if( $gJpgBrandTiming )
     218            $min_bm=15;         
     219        */
     220        $lm = min(40,$this->width/7);
     221        $rm = min(20,$this->width/10);
     222        $tm = max(5,$this->height/7);
     223        $bm = max($min_bm,$this->height/7);
     224        $this->SetMargin($lm,$rm,$tm,$bm);             
     225    }
     226
     227                               
    268228    //---------------
    269     // PUBLIC METHODS
    270 
     229    // PUBLIC METHODS   
     230       
    271231    function SetFont($family,$style=FS_NORMAL,$size=10) {
    272         $this->font_family=$family;
    273         $this->font_style=$style;
    274         $this->font_size=$size*SUPERSAMPLING_SCALE;
    275         $this->font_file='';
    276         if( ($this->font_family==FF_FONT1 || $this->font_family==FF_FONT2) && $this->font_style==FS_BOLD ){
    277             ++$this->font_family;
    278         }
    279         if( $this->font_family > FF_FONT2+1 ) { // A TTF font so get the font file
    280 
    281             // Check that this PHP has support for TTF fonts
    282             if( !function_exists('imagettfbbox') ) {
    283                 // use internal font when php is configured without '--with-ttf'
    284                 $this->font_family = FF_FONT1;
    285 //                JpGraphError::RaiseL(25087);//('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.');
    286             } else {
    287                 $this->font_file = $this->ttf->File($this->font_family,$this->font_style);
    288             }
    289         }
     232        $this->font_family=$family;
     233        $this->font_style=$style;
     234        $this->font_size=$size;
     235        $this->font_file='';
     236        if( ($this->font_family==FF_FONT1 || $this->font_family==FF_FONT2) && $this->font_style==FS_BOLD ){
     237            ++$this->font_family;
     238        }
     239        if( $this->font_family > FF_FONT2+1 ) { // A TTF font so get the font file
     240
     241            // Check that this PHP has support for TTF fonts
     242            if( !function_exists('imagettfbbox') ) {
     243                JpGraphError::RaiseL(25087);//('This PHP build has not been configured with TTF support. You need to recompile your PHP installation with FreeType support.');
     244            }
     245            $this->font_file = $this->ttf->File($this->font_family,$this->font_style);
     246        }
    290247    }
    291248
    292249    // Get the specific height for a text string
    293250    function GetTextHeight($txt="",$angle=0) {
    294         $tmp = preg_split('/\n/',$txt);
    295         $n = count($tmp);
    296         $m=0;
    297         for($i=0; $i< $n; ++$i) {
    298             $m = max($m,strlen($tmp[$i]));
    299         }
    300 
    301         if( $this->font_family <= FF_FONT2+1 ) {
    302             if( $angle==0 ) {
    303                 $h = imagefontheight($this->font_family);
    304                 if( $h === false ) {
    305                     JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
    306                 }
    307 
    308                 return $n*$h;
    309             }
    310             else {
    311                 $w = @imagefontwidth($this->font_family);
    312                 if( $w === false ) {
    313                     JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
    314                 }
    315 
    316                 return $m*$w;
    317             }
    318         }
    319         else {
    320             $bbox = $this->GetTTFBBox($txt,$angle);
    321             return $bbox[1]-$bbox[5]+1;
    322         }
    323     }
    324 
     251        $tmp = split("\n",$txt);
     252        $n = count($tmp);
     253        $m=0;
     254        for($i=0; $i< $n; ++$i)
     255            $m = max($m,strlen($tmp[$i]));
     256
     257        if( $this->font_family <= FF_FONT2+1 ) {
     258            if( $angle==0 ) {
     259                $h = imagefontheight($this->font_family);
     260                if( $h === false ) {
     261                    JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
     262                }
     263
     264                return $n*$h;
     265            }
     266            else {
     267                $w = @imagefontwidth($this->font_family);
     268                if( $w === false ) {
     269                    JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
     270                }
     271
     272                return $m*$w;
     273            }
     274        }
     275        else {
     276            $bbox = $this->GetTTFBBox($txt,$angle);
     277            return $bbox[1]-$bbox[5];
     278        }
     279    }
     280       
    325281    // Estimate font height
    326282    function GetFontHeight($angle=0) {
    327         $txt = "XOMg";
    328         return $this->GetTextHeight($txt,$angle);
    329     }
    330 
     283        $txt = "XOMg";
     284        return $this->GetTextHeight($txt,$angle);
     285    }
     286       
    331287    // Approximate font width with width of letter "O"
    332288    function GetFontWidth($angle=0) {
    333         $txt = 'O';
    334         return $this->GetTextWidth($txt,$angle);
    335     }
    336 
    337     // Get actual width of text in absolute pixels. Note that the width is the
    338     // texts projected with onto the x-axis. Call with angle=0 to get the true
    339     // etxt width.
     289        $txt = 'O';
     290        return $this->GetTextWidth($txt,$angle);
     291    }
     292       
     293    // Get actual width of text in absolute pixels
    340294    function GetTextWidth($txt,$angle=0) {
    341295
    342         $tmp = preg_split('/\n/',$txt);
    343         $n = count($tmp);
    344         if( $this->font_family <= FF_FONT2+1 ) {
    345 
    346             $m=0;
    347             for($i=0; $i < $n; ++$i) {
    348                 $l=strlen($tmp[$i]);
    349                 if( $l > $m ) {
    350                     $m = $l;
    351                 }
    352             }
    353 
    354             if( $angle==0 ) {
    355                 $w = @imagefontwidth($this->font_family);
    356                 if( $w === false ) {
    357                     JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
    358                 }
    359                 return $m*$w;
    360             }
    361             else {
    362                 // 90 degrees internal so height becomes width
    363                 $h = @imagefontheight($this->font_family);
    364                 if( $h === false ) {
    365                     JpGraphError::RaiseL(25089);//('You have a misconfigured GD font support. The call to imagefontheight() fails.');
    366                 }
    367                 return $n*$h;
    368             }
    369         }
    370         else {
    371             // For TTF fonts we must walk through a lines and find the
    372             // widest one which we use as the width of the multi-line
    373             // paragraph
    374             $m=0;
    375             for( $i=0; $i < $n; ++$i ) {
    376                 $bbox = $this->GetTTFBBox($tmp[$i],$angle);
    377                 $mm =  $bbox[2] - $bbox[0];
    378                 if( $mm > $m )
    379                     $m = $mm;
    380             }
    381             return $m;
    382         }
    383     }
    384 
    385 
     296        $tmp = split("\n",$txt);
     297        $n = count($tmp);
     298        if( $this->font_family <= FF_FONT2+1 ) {
     299
     300            $m=0;
     301            for($i=0; $i < $n; ++$i) {
     302                $l=strlen($tmp[$i]);
     303                if( $l > $m ) {
     304                    $m = $l;
     305                }
     306            }
     307
     308            if( $angle==0 ) {
     309                $w = @imagefontwidth($this->font_family);
     310                if( $w === false ) {
     311                    JpGraphError::RaiseL(25088);//('You have a misconfigured GD font support. The call to imagefontwidth() fails.');
     312                }
     313                return $m*$w;
     314            }
     315            else {
     316                // 90 degrees internal so height becomes width
     317                $h = @imagefontheight($this->font_family);
     318                if( $h === false ) {
     319                    JpGraphError::RaiseL(25089);//('You have a misconfigured GD font support. The call to imagefontheight() fails.');
     320                }
     321                return $n*$h;
     322            }
     323        }
     324        else {
     325            // For TTF fonts we must walk through a lines and find the
     326            // widest one which we use as the width of the multi-line
     327            // paragraph
     328            $m=0;
     329            for( $i=0; $i < $n; ++$i ) {
     330                $bbox = $this->GetTTFBBox($tmp[$i],$angle);
     331                $mm =  $bbox[2] - $bbox[0];
     332                if( $mm > $m )
     333                    $m = $mm;
     334            }
     335            return $m;
     336        }
     337    }
     338       
    386339    // Draw text with a box around it
    387340    function StrokeBoxedText($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black",
    388                              $shadowcolor=false,$paragraph_align="left",
    389                              $xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) {
    390 
    391                 $oldx = $this->lastx;
    392                 $oldy = $this->lasty;
    393 
    394         if( !is_numeric($dir) ) {
    395             if( $dir=="h" ) $dir=0;
    396             elseif( $dir=="v" ) $dir=90;
    397             else JpGraphError::RaiseL(25090,$dir);//(" Unknown direction specified in call to StrokeBoxedText() [$dir]");
    398         }
    399 
    400         if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) {
    401             $width=$this->GetTextWidth($txt,$dir) ;
    402             $height=$this->GetTextHeight($txt,$dir) ;
    403         }
    404         else {
    405             $width=$this->GetBBoxWidth($txt,$dir) ;
    406             $height=$this->GetBBoxHeight($txt,$dir) ;
    407         }
    408 
    409         $height += 2*$ymarg;
    410         $width  += 2*$xmarg;
    411 
    412         if( $this->text_halign=="right" )      $x -= $width;
    413         elseif( $this->text_halign=="center" ) $x -= $width/2;
    414 
    415         if( $this->text_valign=="bottom" )     $y -= $height;
    416         elseif( $this->text_valign=="center" ) $y -= $height/2;
    417 
    418         $olda = $this->SetAngle(0);
    419 
    420         if( $shadowcolor ) {
    421             $this->PushColor($shadowcolor);
    422             $this->FilledRoundedRectangle($x-$xmarg+$dropwidth,$y-$ymarg+$dropwidth,
    423                                           $x+$width+$dropwidth,$y+$height-$ymarg+$dropwidth,
    424                                           $cornerradius);
    425             $this->PopColor();
    426             $this->PushColor($fcolor);
    427             $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg,
    428                                           $x+$width,$y+$height-$ymarg,
    429                                           $cornerradius);
    430             $this->PopColor();
    431             $this->PushColor($bcolor);
    432             $this->RoundedRectangle($x-$xmarg,$y-$ymarg,
    433                                     $x+$width,$y+$height-$ymarg,$cornerradius);
    434             $this->PopColor();
    435         }
    436         else {
    437             if( $fcolor ) {
    438                 $oc=$this->current_color;
    439                 $this->SetColor($fcolor);
    440                 $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius);
    441                 $this->current_color=$oc;
     341                             $shadowcolor=false,$paragraph_align="left",
     342                             $xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) {
     343
     344        if( !is_numeric($dir) ) {
     345            if( $dir=="h" ) $dir=0;
     346            elseif( $dir=="v" ) $dir=90;
     347            else JpGraphError::RaiseL(25090,$dir);//(" Unknown direction specified in call to StrokeBoxedText() [$dir]");
     348        }
     349               
     350        if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) {       
     351            $width=$this->GetTextWidth($txt,$dir) ;
     352            $height=$this->GetTextHeight($txt,$dir) ;
     353        }
     354        else {
     355            $width=$this->GetBBoxWidth($txt,$dir) ;
     356            $height=$this->GetBBoxHeight($txt,$dir) ;
     357        }
     358
     359        $height += 2*$ymarg;
     360        $width  += 2*$xmarg;
     361
     362        if( $this->text_halign=="right" ) $x -= $width;
     363        elseif( $this->text_halign=="center" ) $x -= $width/2;
     364        if( $this->text_valign=="bottom" ) $y -= $height;
     365        elseif( $this->text_valign=="center" ) $y -= $height/2;
     366       
     367        $olda = $this->SetAngle(0);
     368
     369        if( $shadowcolor ) {
     370            $this->PushColor($shadowcolor);
     371            $this->FilledRoundedRectangle($x-$xmarg+$dropwidth,$y-$ymarg+$dropwidth,
     372                                          $x+$width+$dropwidth,$y+$height-$ymarg+$dropwidth,
     373                                          $cornerradius);
     374            $this->PopColor();
     375            $this->PushColor($fcolor);
     376            $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg,
     377                                          $x+$width,$y+$height-$ymarg,
     378                                          $cornerradius);               
     379            $this->PopColor();
     380            $this->PushColor($bcolor);
     381            $this->RoundedRectangle($x-$xmarg,$y-$ymarg,
     382                                    $x+$width,$y+$height-$ymarg,$cornerradius);
     383            $this->PopColor();
     384        }
     385        else {
     386            if( $fcolor ) {
     387                $oc=$this->current_color;
     388                $this->SetColor($fcolor);
     389                $this->FilledRoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius);
     390                $this->current_color=$oc;
     391            }
     392            if( $bcolor ) {
     393                $oc=$this->current_color;
     394                $this->SetColor($bcolor);                       
     395                $this->RoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius);
     396                $this->current_color=$oc;                       
     397            }
     398        }
     399               
     400        $h=$this->text_halign;
     401        $v=$this->text_valign;
     402        $this->SetTextAlign("left","top");
     403        $this->StrokeText($x, $y, $txt, $dir, $paragraph_align);
     404        $bb = array($x-$xmarg,$y+$height-$ymarg,$x+$width,$y+$height-$ymarg,
     405                    $x+$width,$y-$ymarg,$x-$xmarg,$y-$ymarg);
     406        $this->SetTextAlign($h,$v);
     407
     408        $this->SetAngle($olda);
     409
     410        return $bb;
     411    }
     412
     413    // Set text alignment       
     414    function SetTextAlign($halign,$valign="bottom") {
     415        $this->text_halign=$halign;
     416        $this->text_valign=$valign;
     417    }
     418       
     419
     420    function _StrokeBuiltinFont($x,$y,$txt,$dir=0,$paragraph_align="left",&$aBoundingBox,$aDebug=false) {
     421
     422        if( is_numeric($dir) && $dir!=90 && $dir!=0)
     423            JpGraphError::RaiseL(25091);//(" Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead.");
     424
     425        $h=$this->GetTextHeight($txt);
     426        $fh=$this->GetFontHeight();
     427        $w=$this->GetTextWidth($txt);
     428       
     429        if( $this->text_halign=="right")                               
     430            $x -= $dir==0 ? $w : $h;
     431        elseif( $this->text_halign=="center" ) {
     432            // For center we subtract 1 pixel since this makes the middle
     433            // be prefectly in the middle
     434            $x -= $dir==0 ? $w/2-1 : $h/2;
     435        }
     436        if( $this->text_valign=="top" )
     437            $y += $dir==0 ? $h : $w;
     438        elseif( $this->text_valign=="center" )                         
     439            $y += $dir==0 ? $h/2 : $w/2;
     440       
     441        if( $dir==90 ) {
     442            imagestringup($this->img,$this->font_family,$x,$y,$txt,$this->current_color);
     443            $aBoundingBox = array(round($x),round($y),round($x),round($y-$w),round($x+$h),round($y-$w),round($x+$h),round($y));
     444            if( $aDebug ) {
     445                // Draw bounding box
     446                $this->PushColor('green');
     447                $this->Polygon($aBoundingBox,true);
     448                $this->PopColor();
     449            }
     450        }
     451        else {
     452            if( preg_match('/\n/',$txt) ) {
     453                $tmp = split("\n",$txt);
     454                for($i=0; $i < count($tmp); ++$i) {
     455                    $w1 = $this->GetTextWidth($tmp[$i]);
     456                    if( $paragraph_align=="left" ) {
     457                        imagestring($this->img,$this->font_family,$x,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color);
     458                    }
     459                    elseif( $paragraph_align=="right" ) {
     460                        imagestring($this->img,$this->font_family,$x+($w-$w1),
     461                                    $y-$h+1+$i*$fh,$tmp[$i],$this->current_color);
     462                    }
     463                    else {
     464                        imagestring($this->img,$this->font_family,$x+$w/2-$w1/2,
     465                                    $y-$h+1+$i*$fh,$tmp[$i],$this->current_color);
     466                    }
     467                }
     468            }
     469            else {
     470                //Put the text
     471                imagestring($this->img,$this->font_family,$x,$y-$h+1,$txt,$this->current_color);
     472            }
     473            if( $aDebug ) {
     474                // Draw the bounding rectangle and the bounding box
     475                $p1 = array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y));
     476               
     477                // Draw bounding box
     478                $this->PushColor('green');
     479                $this->Polygon($p1,true);
     480                $this->PopColor();
     481
    442482            }
    443             if( $bcolor ) {
    444                 $oc=$this->current_color;
    445                 $this->SetColor($bcolor);
    446                 $this->RoundedRectangle($x-$xmarg,$y-$ymarg,$x+$width,$y+$height-$ymarg,$cornerradius);
    447                 $this->current_color=$oc;
     483            $aBoundingBox=array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y));
     484        }
     485    }
     486
     487    function AddTxtCR($aTxt) {
     488        // If the user has just specified a '\n'
     489        // instead of '\n\t' we have to add '\r' since
     490        // the width will be too muchy otherwise since when
     491        // we print we stroke the individually lines by hand.
     492        $e = explode("\n",$aTxt);
     493        $n = count($e);
     494        for($i=0; $i<$n; ++$i) {
     495            $e[$i]=str_replace("\r","",$e[$i]);
     496        }
     497        return implode("\n\r",$e);
     498    }
     499
     500    function GetTTFBBox($aTxt,$aAngle=0) {
     501        $bbox = @ImageTTFBBox($this->font_size,$aAngle,$this->font_file,$aTxt);
     502        if( $bbox === false ) {
     503            JpGraphError::RaiseL(25092,$this->font_file);
     504//("There is either a configuration problem with TrueType or a problem reading font file (".$this->font_file."). Make sure file exists and is in a readable place for the HTTP process. (If 'basedir' restriction is enabled in PHP then the font file must be located in the document root.). It might also be a wrongly installed FreeType library. Try uppgrading to at least FreeType 2.1.13 and recompile GD with the correct setup so it can find the new FT library.");
     505        }
     506        return $bbox;
     507    }
     508
     509    function GetBBoxTTF($aTxt,$aAngle=0) {
     510        // Normalize the bounding box to become a minimum
     511        // enscribing rectangle
     512
     513        $aTxt = $this->AddTxtCR($aTxt);
     514
     515        if( !is_readable($this->font_file) ) {
     516            JpGraphError::RaiseL(25093,$this->font_file);
     517//('Can not read font file ('.$this->font_file.') in call to Image::GetBBoxTTF. Please make sure that you have set a font before calling this method and that the font is installed in the TTF directory.');
     518        }
     519        $bbox = $this->GetTTFBBox($aTxt,$aAngle);
     520
     521        if( $aAngle==0 )
     522            return $bbox;
     523        if( $aAngle >= 0 ) {
     524            if(  $aAngle <= 90 ) { //<=0               
     525                $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1],
     526                              $bbox[2],$bbox[5],$bbox[6],$bbox[5]);
     527            }
     528            elseif(  $aAngle <= 180 ) { //<= 2
     529                $bbox = array($bbox[4],$bbox[7],$bbox[0],$bbox[7],
     530                              $bbox[0],$bbox[3],$bbox[4],$bbox[3]);
     531            }
     532            elseif(  $aAngle <= 270 )  { //<= 3
     533                $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5],
     534                              $bbox[6],$bbox[1],$bbox[2],$bbox[1]);
     535            }
     536            else {
     537                $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3],
     538                              $bbox[4],$bbox[7],$bbox[0],$bbox[7]);
     539            }
     540        }
     541        elseif(  $aAngle < 0 ) {
     542            if( $aAngle <= -270 ) { // <= -3
     543                $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1],
     544                              $bbox[2],$bbox[5],$bbox[6],$bbox[5]);
     545            }
     546            elseif( $aAngle <= -180 ) { // <= -2
     547                $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3],
     548                              $bbox[4],$bbox[7],$bbox[0],$bbox[7]);
     549            }
     550            elseif( $aAngle <= -90 ) { // <= -1
     551                $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5],
     552                              $bbox[6],$bbox[1],$bbox[2],$bbox[1]);
     553            }
     554            else {
     555                $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3],
     556                              $bbox[4],$bbox[7],$bbox[0],$bbox[7]);
     557            }
     558        }       
     559        return $bbox;
     560    }
     561
     562    function GetBBoxHeight($aTxt,$aAngle=0) {
     563        $box = $this->GetBBoxTTF($aTxt,$aAngle);
     564        return $box[1]-$box[7]+1;
     565    }
     566
     567    function GetBBoxWidth($aTxt,$aAngle=0) {
     568        $box = $this->GetBBoxTTF($aTxt,$aAngle);
     569        return $box[2]-$box[0]+1;       
     570    }
     571
     572    function _StrokeTTF($x,$y,$txt,$dir=0,$paragraph_align="left",&$aBoundingBox,$debug=false) {
     573
     574        // Setupo default inter line margin for paragraphs to
     575        // 25% of the font height.
     576        $ConstLineSpacing = 0.25 ;
     577
     578        // Remember the anchor point before adjustment
     579        if( $debug ) {
     580            $ox=$x;
     581            $oy=$y;
     582        }
     583
     584        if( !preg_match('/\n/',$txt) || ($dir>0 && preg_match('/\n/',$txt)) ) {
     585            // Format a single line
     586
     587            $txt = $this->AddTxtCR($txt);
     588
     589            $bbox=$this->GetBBoxTTF($txt,$dir);
     590           
     591            // Align x,y ot lower left corner of bbox
     592            $x -= $bbox[0];
     593            $y -= $bbox[1];
     594
     595            // Note to self: "topanchor" is deprecated after we changed the
     596            // bopunding box stuff.
     597            if( $this->text_halign=="right" || $this->text_halign=="topanchor" )
     598                $x -= $bbox[2]-$bbox[0];
     599            elseif( $this->text_halign=="center" ) $x -= ($bbox[2]-$bbox[0])/2;
     600           
     601            if( $this->text_valign=="top" ) $y += abs($bbox[5])+$bbox[1];
     602            elseif( $this->text_valign=="center" ) $y -= ($bbox[5]-$bbox[1])/2;
     603
     604            ImageTTFText ($this->img, $this->font_size, $dir, $x, $y,
     605                          $this->current_color,$this->font_file,$txt);
     606
     607            // Calculate and return the co-ordinates for the bounding box
     608            $box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$txt);
     609            $p1 = array();
     610
     611
     612            for($i=0; $i < 4; ++$i) {
     613                $p1[] = round($box[$i*2]+$x);
     614                $p1[] = round($box[$i*2+1]+$y);
     615            }
     616            $aBoundingBox = $p1;
     617
     618            // Debugging code to highlight the bonding box and bounding rectangle
     619            // For text at 0 degrees the bounding box and bounding rectangle are the
     620            // same
     621            if( $debug ) {
     622                // Draw the bounding rectangle and the bounding box
     623                $box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$txt);
     624                $p = array();
     625                $p1 = array();
     626                for($i=0; $i < 4; ++$i) {
     627                    $p[] = $bbox[$i*2]+$x;
     628                    $p[] = $bbox[$i*2+1]+$y;
     629                    $p1[] = $box[$i*2]+$x;
     630                    $p1[] = $box[$i*2+1]+$y;
     631                }
     632
     633                // Draw bounding box
     634                $this->PushColor('green');
     635                $this->Polygon($p1,true);
     636                $this->PopColor();
     637               
     638                // Draw bounding rectangle
     639                $this->PushColor('darkgreen');
     640                $this->Polygon($p,true);
     641                $this->PopColor();
     642               
     643                // Draw a cross at the anchor point
     644                $this->PushColor('red');
     645                $this->Line($ox-15,$oy,$ox+15,$oy);
     646                $this->Line($ox,$oy-15,$ox,$oy+15);
     647                $this->PopColor();
    448648            }
    449         }
    450 
    451         $h=$this->text_halign;
    452         $v=$this->text_valign;
    453         $this->SetTextAlign("left","top");
    454 
    455         $debug=false;
    456         $this->StrokeText($x, $y, $txt, $dir, $paragraph_align,$debug);
    457 
    458         $bb = array($x-$xmarg,$y+$height-$ymarg,$x+$width,$y+$height-$ymarg,
    459                     $x+$width,$y-$ymarg,$x-$xmarg,$y-$ymarg);
    460         $this->SetTextAlign($h,$v);
    461 
    462         $this->SetAngle($olda);
    463                 $this->lastx = $oldx;
    464                 $this->lasty = $oldy;
    465 
    466         return $bb;
    467     }
    468 
    469     // Draw text with a box around it. This time the box will be rotated
    470     // with the text. The previous method will just make a larger enough non-rotated
    471     // box to hold the text inside.
    472     function StrokeBoxedText2($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black",
    473                              $shadowcolor=false,$paragraph_align="left",
    474                              $xmarg=6,$ymarg=4,$cornerradius=0,$dropwidth=3) {
    475 
    476        // This version of boxed text will stroke a rotated box round the text
    477        // thta will follow the angle of the text.
    478        // This has two implications:
    479        // 1) This methos will only support TTF fonts
    480        // 2) The only two alignment that makes sense are centered or baselined
    481 
    482        if( $this->font_family <= FF_FONT2+1 ) {
    483            JpGraphError::RaiseL(25131);//StrokeBoxedText2() Only support TTF fonts and not built in bitmap fonts
    484        }
    485 
    486                 $oldx = $this->lastx;
    487                 $oldy = $this->lasty;
    488         $dir = $this->NormAngle($dir);
    489 
    490         if( !is_numeric($dir) ) {
    491             if( $dir=="h" ) $dir=0;
    492             elseif( $dir=="v" ) $dir=90;
    493             else JpGraphError::RaiseL(25090,$dir);//(" Unknown direction specified in call to StrokeBoxedText() [$dir]");
    494         }
    495 
    496         $width=$this->GetTextWidth($txt,0) + 2*$xmarg;
    497         $height=$this->GetTextHeight($txt,0) + 2*$ymarg ;
    498         $rect_width=$this->GetBBoxWidth($txt,$dir) ;
    499         $rect_height=$this->GetBBoxHeight($txt,$dir) ;
    500 
    501         $baseline_offset = $this->bbox_cache[1]-1;
    502 
    503         if( $this->text_halign=="center" ) {
    504             if( $dir >= 0 && $dir <= 90 ) {
    505 
    506                 $x -= $rect_width/2;
    507                 $x += sin($dir*M_PI/180)*$height;
    508                 $y += $rect_height/2;               
    509 
    510             } elseif( $dir >= 270 && $dir <= 360 ) {
    511 
    512                 $x -= $rect_width/2;
    513                 $y -= $rect_height/2;
    514                 $y += cos($dir*M_PI/180)*$height;
    515 
    516             } elseif( $dir >= 90 && $dir <= 180 ) {
    517 
    518                 $x += $rect_width/2;
    519                 $y += $rect_height/2;
    520                 $y += cos($dir*M_PI/180)*$height;
    521 
    522             }
    523             else {
    524                 // $dir > 180 &&  $dir < 270
    525                 $x += $rect_width/2;
    526                 $x += sin($dir*M_PI/180)*$height;
    527                 $y -= $rect_height/2;
    528             }
    529         }
    530 
    531         // Rotate the box around this point
    532         $this->SetCenter($x,$y);
    533         $olda = $this->SetAngle(-$dir);
    534 
    535         // We need to use adjusted coordinats for the box to be able
    536         // to draw the box below the baseline. This cannot be done before since
    537         // the rotating point must be the original x,y since that is arounbf the
    538         // point where the text will rotate and we cannot change this since
    539         // that is where the GD/GreeType will rotate the text
    540 
    541 
    542         // For smaller <14pt font we need to do some additional
    543         // adjustments to make it look good
    544         if( $this->font_size < 14 ) {
    545             $x -= 2;
    546             $y += 2;
    547         }
    548         else {
    549           //  $y += $baseline_offset;
    550         }
    551 
    552         if( $shadowcolor ) {
    553             $this->PushColor($shadowcolor);
    554             $this->FilledRectangle($x-$xmarg+$dropwidth,$y+$ymarg+$dropwidth-$height,
    555                                           $x+$width+$dropwidth,$y+$ymarg+$dropwidth);
    556                                           //$cornerradius);
    557             $this->PopColor();
    558             $this->PushColor($fcolor);
    559             $this->FilledRectangle($x-$xmarg, $y+$ymarg-$height,
    560                                           $x+$width, $y+$ymarg);
    561                                           //$cornerradius);
    562             $this->PopColor();
    563             $this->PushColor($bcolor);
    564             $this->Rectangle($x-$xmarg,$y+$ymarg-$height,
    565                                     $x+$width,$y+$ymarg);
    566                                     //$cornerradius);
    567             $this->PopColor();
    568         }
    569         else {
    570             if( $fcolor ) {
    571                 $oc=$this->current_color;
    572                 $this->SetColor($fcolor);
    573                 $this->FilledRectangle($x-$xmarg,$y+$ymarg-$height,$x+$width,$y+$ymarg);//,$cornerradius);
    574                 $this->current_color=$oc;
    575             }
    576             if( $bcolor ) {
    577                 $oc=$this->current_color;
    578                 $this->SetColor($bcolor);
    579                 $this->Rectangle($x-$xmarg,$y+$ymarg-$height,$x+$width,$y+$ymarg);//,$cornerradius);
    580                 $this->current_color=$oc;
    581             }
    582         }
    583 
    584         if( $this->font_size < 14 ) {
    585             $x += 2;
    586             $y -= 2;
    587         }
    588         else {
    589 
    590             // Restore the original y before we stroke the text
    591            // $y -= $baseline_offset;
    592 
    593         }
    594 
    595         $this->SetCenter(0,0);
    596         $this->SetAngle($olda);
    597 
    598         $h=$this->text_halign;
    599         $v=$this->text_valign;
    600         if( $this->text_halign == 'center') {
    601             $this->SetTextAlign('center','basepoint');
    602         }
    603         else {
    604             $this->SetTextAlign('basepoint','basepoint');
    605         }
    606 
    607         $debug=false;
    608         $this->StrokeText($x, $y, $txt, $dir, $paragraph_align,$debug);
    609 
    610         $bb = array($x-$xmarg, $y+$height-$ymarg,
    611                     $x+$width, $y+$height-$ymarg,
    612                     $x+$width, $y-$ymarg,
    613                     $x-$xmarg, $y-$ymarg);
    614 
    615         $this->SetTextAlign($h,$v);
    616         $this->SetAngle($olda);
    617 
    618                 $this->lastx = $oldx;
    619                 $this->lasty = $oldy;
    620 
    621         return $bb;
    622     }
    623 
    624     // Set text alignment
    625     function SetTextAlign($halign,$valign="bottom") {
    626         $this->text_halign=$halign;
    627         $this->text_valign=$valign;
    628     }
    629 
    630     function _StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,&$aBoundingBox,$aDebug=false) {
    631 
    632         if( is_numeric($dir) && $dir!=90 && $dir!=0)
    633         JpGraphError::RaiseL(25091);//(" Internal font does not support drawing text at arbitrary angle. Use TTF fonts instead.");
    634 
    635         $h=$this->GetTextHeight($txt);
    636         $fh=$this->GetFontHeight();
    637         $w=$this->GetTextWidth($txt);
    638 
    639         if( $this->text_halign=="right") {
    640             $x -= $dir==0 ? $w : $h;
    641         }
    642         elseif( $this->text_halign=="center" ) {
    643             // For center we subtract 1 pixel since this makes the middle
    644             // be prefectly in the middle
    645             $x -= $dir==0 ? $w/2-1 : $h/2;
    646         }
    647         if( $this->text_valign=="top" ) {
    648             $y += $dir==0 ? $h : $w;
    649         }
    650         elseif( $this->text_valign=="center" ) {
    651             $y += $dir==0 ? $h/2 : $w/2;
    652         }
    653 
    654         $use_font = $this->font_family;
    655 
    656         if( $dir==90 ) {
    657             imagestringup($this->img,$use_font,$x,$y,$txt,$this->current_color);
    658             $aBoundingBox = array(round($x),round($y),round($x),round($y-$w),round($x+$h),round($y-$w),round($x+$h),round($y));
    659             if( $aDebug ) {
    660                 // Draw bounding box
    661                 $this->PushColor('green');
    662                 $this->Polygon($aBoundingBox,true);
    663                 $this->PopColor();
    664             }
    665         }
    666         else {
    667             if( preg_match('/\n/',$txt) ) {
    668                 $tmp = preg_split('/\n/',$txt);
    669                 for($i=0; $i < count($tmp); ++$i) {
    670                     $w1 = $this->GetTextWidth($tmp[$i]);
    671                     if( $paragraph_align=="left" ) {
    672                         imagestring($this->img,$use_font,$x,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color);
    673                     }
    674                     elseif( $paragraph_align=="right" ) {
    675                         imagestring($this->img,$use_font,$x+($w-$w1),$y-$h+1+$i*$fh,$tmp[$i],$this->current_color);
    676                     }
    677                     else {
    678                         imagestring($this->img,$use_font,$x+$w/2-$w1/2,$y-$h+1+$i*$fh,$tmp[$i],$this->current_color);
    679                     }
    680                 }
    681             }
    682             else {
    683                 //Put the text
    684                 imagestring($this->img,$use_font,$x,$y-$h+1,$txt,$this->current_color);
    685             }
    686             if( $aDebug ) {
    687                 // Draw the bounding rectangle and the bounding box
    688                 $p1 = array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y));
    689 
    690                 // Draw bounding box
    691                 $this->PushColor('green');
    692                 $this->Polygon($p1,true);
    693                 $this->PopColor();
    694 
    695             }
    696             $aBoundingBox=array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y));
    697         }
    698     }
    699 
    700     function AddTxtCR($aTxt) {
    701         // If the user has just specified a '\n'
    702         // instead of '\n\t' we have to add '\r' since
    703         // the width will be too muchy otherwise since when
    704         // we print we stroke the individually lines by hand.
    705         $e = explode("\n",$aTxt);
    706         $n = count($e);
    707         for($i=0; $i<$n; ++$i) {
    708             $e[$i]=str_replace("\r","",$e[$i]);
    709         }
    710         return implode("\n\r",$e);
    711     }
    712 
    713     function NormAngle($a) {
    714         // Normalize angle in degrees
    715         // Normalize angle to be between 0-360
    716         while( $a > 360 )
    717             $a -= 360;
    718         while( $a < -360 )
    719             $a += 360;
    720         if( $a < 0 )
    721             $a = 360 + $a;
    722         return $a;
    723     }
    724 
    725     function imagettfbbox_fixed($size, $angle, $fontfile, $text) {
    726 
    727 
    728         if( ! USE_LIBRARY_IMAGETTFBBOX ) {
    729 
    730             $bbox = @imagettfbbox($size, $angle, $fontfile, $text);
    731             if( $bbox === false ) {
    732                 JpGraphError::RaiseL(25092,$this->font_file);
    733                 //("There is either a configuration problem with TrueType or a problem reading font file (".$this->font_file."). Make sure file exists and is in a readable place for the HTTP process. (If 'basedir' restriction is enabled in PHP then the font file must be located in the document root.). It might also be a wrongly installed FreeType library. Try uppgrading to at least FreeType 2.1.13 and recompile GD with the correct setup so it can find the new FT library.");
    734             }
    735             $this->bbox_cache = $bbox;
    736             return $bbox;
    737         }
    738 
    739         // The built in imagettfbbox is buggy for angles != 0 so
    740         // we calculate this manually by getting the bounding box at
    741         // angle = 0 and then rotate the bounding box manually
    742         $bbox = @imagettfbbox($size, 0, $fontfile, $text);
    743         if( $bbox === false ) {
    744             JpGraphError::RaiseL(25092,$this->font_file);
    745             //("There is either a configuration problem with TrueType or a problem reading font file (".$this->font_file."). Make sure file exists and is in a readable place for the HTTP process. (If 'basedir' restriction is enabled in PHP then the font file must be located in the document root.). It might also be a wrongly installed FreeType library. Try uppgrading to at least FreeType 2.1.13 and recompile GD with the correct setup so it can find the new FT library.");
    746         }
    747 
    748         $angle = $this->NormAngle($angle);
    749 
    750         $a = $angle*M_PI/180;
    751         $ca = cos($a);
    752         $sa = sin($a);
    753         $ret = array();
    754 
    755         // We always add 1 pixel to the left since the left edge of the bounding
    756         // box is sometimes coinciding with the first pixel of the text
    757         //$bbox[0] -= 1;
    758         //$bbox[6] -= 1;
    759        
    760         // For roatated text we need to add extra width for rotated
    761         // text since the kerning and stroking of the TTF is not the same as for
    762         // text at a 0 degree angle
    763 
    764         if( $angle > 0.001 && abs($angle-360) > 0.001 ) {
    765             $h = abs($bbox[7]-$bbox[1]);
    766             $w = abs($bbox[2]-$bbox[0]);
    767 
    768             $bbox[0] -= 2;
    769             $bbox[6] -= 2;
    770             // The width is underestimated so compensate for that
    771             $bbox[2] += round($w*0.06);
    772             $bbox[4] += round($w*0.06);
    773 
    774             // and we also need to compensate with increased height
    775             $bbox[5] -= round($h*0.1);
    776             $bbox[7] -= round($h*0.1);
    777 
    778             if( $angle > 90 ) {
    779                 // For angles > 90 we also need to extend the height further down
    780                 // by the baseline since that is also one more problem
    781                 $bbox[1] += round($h*0.15);
    782                 $bbox[3] += round($h*0.15);
    783 
    784                 // and also make it slighty less height
    785                 $bbox[7] += round($h*0.05);
    786                 $bbox[5] += round($h*0.05);
    787 
    788                 // And we need to move the box slightly top the rright (from a tetx perspective)
    789                 $bbox[0] += round($w*0.02);
    790                 $bbox[6] += round($w*0.02);
    791 
    792                 if( $angle > 180 ) {
    793                     // And we need to move the box slightly to the left (from a text perspective)
    794                     $bbox[0] -= round($w*0.02);
    795                     $bbox[6] -= round($w*0.02);
    796                     $bbox[2] -= round($w*0.02);
    797                     $bbox[4] -= round($w*0.02);
    798 
    799                 }
    800 
    801             }
    802             for($i = 0; $i < 7; $i += 2) {
    803                 $ret[$i] = round($bbox[$i] * $ca + $bbox[$i+1] * $sa);
    804                 $ret[$i+1] = round($bbox[$i+1] * $ca - $bbox[$i] * $sa);
    805             }
    806             $this->bbox_cache = $ret;
    807             return $ret;
    808         }
    809         else {
    810             $this->bbox_cache = $bbox;
    811             return $bbox;
    812         }
    813     }
    814 
    815     // Deprecated
    816     function GetTTFBBox($aTxt,$aAngle=0) {
    817         $bbox = $this->imagettfbbox_fixed($this->font_size,$aAngle,$this->font_file,$aTxt);
    818          return $bbox;
    819     }
    820 
    821     function GetBBoxTTF($aTxt,$aAngle=0) {
    822         // Normalize the bounding box to become a minimum
    823         // enscribing rectangle
    824 
    825         $aTxt = $this->AddTxtCR($aTxt);
    826 
    827         if( !is_readable($this->font_file) ) {
    828             JpGraphError::RaiseL(25093,$this->font_file);
    829             //('Can not read font file ('.$this->font_file.') in call to Image::GetBBoxTTF. Please make sure that you have set a font before calling this method and that the font is installed in the TTF directory.');
    830         }
    831         $bbox = $this->imagettfbbox_fixed($this->font_size,$aAngle,$this->font_file,$aTxt);
    832 
    833         if( $aAngle==0 ) return $bbox;
    834 
    835         if( $aAngle >= 0 ) {
    836             if(  $aAngle <= 90 ) { //<=0
    837                 $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1],
    838                               $bbox[2],$bbox[5],$bbox[6],$bbox[5]);
    839             }
    840             elseif(  $aAngle <= 180 ) { //<= 2
    841                 $bbox = array($bbox[4],$bbox[7],$bbox[0],$bbox[7],
    842                               $bbox[0],$bbox[3],$bbox[4],$bbox[3]);
    843             }
    844             elseif(  $aAngle <= 270 )  { //<= 3
    845                 $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5],
    846                               $bbox[6],$bbox[1],$bbox[2],$bbox[1]);
    847             }
    848             else {
    849                 $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3],
    850                               $bbox[4],$bbox[7],$bbox[0],$bbox[7]);
    851             }
    852         }
    853         elseif(  $aAngle < 0 ) {
    854             if( $aAngle <= -270 ) { // <= -3
    855                 $bbox = array($bbox[6],$bbox[1],$bbox[2],$bbox[1],
    856                               $bbox[2],$bbox[5],$bbox[6],$bbox[5]);
    857             }
    858             elseif( $aAngle <= -180 ) { // <= -2
    859                 $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3],
    860                               $bbox[4],$bbox[7],$bbox[0],$bbox[7]);
    861             }
    862             elseif( $aAngle <= -90 ) { // <= -1
    863                 $bbox = array($bbox[2],$bbox[5],$bbox[6],$bbox[5],
    864                               $bbox[6],$bbox[1],$bbox[2],$bbox[1]);
    865             }
    866             else {
    867                 $bbox = array($bbox[0],$bbox[3],$bbox[4],$bbox[3],
    868                               $bbox[4],$bbox[7],$bbox[0],$bbox[7]);
    869             }
    870         }
    871         return $bbox;
    872     }
    873 
    874     function GetBBoxHeight($aTxt,$aAngle=0) {
    875         $box = $this->GetBBoxTTF($aTxt,$aAngle);
    876         return abs($box[7]-$box[1]);
    877     }
    878 
    879     function GetBBoxWidth($aTxt,$aAngle=0) {
    880         $box = $this->GetBBoxTTF($aTxt,$aAngle);
    881         return $box[2]-$box[0]+1;
    882     }
    883 
    884 
    885     function _StrokeTTF($x,$y,$txt,$dir,$paragraph_align,&$aBoundingBox,$debug=false) {
    886 
    887         // Setup default inter line margin for paragraphs to be
    888         // 3% of the font height.
    889         $ConstLineSpacing = 0.03 ;
    890 
    891         // Remember the anchor point before adjustment
    892         if( $debug ) {
    893             $ox=$x;
    894             $oy=$y;
    895         }
    896 
    897         if( !preg_match('/\n/',$txt) || ($dir>0 && preg_match('/\n/',$txt)) ) {
    898             // Format a single line
    899 
    900             $txt = $this->AddTxtCR($txt);
    901             $bbox=$this->GetBBoxTTF($txt,$dir);
    902             $width  = $this->GetBBoxWidth($txt,$dir);
    903             $height = $this->GetBBoxHeight($txt,$dir);
    904 
    905             // The special alignment "basepoint" is mostly used internally
    906             // in the library. This will put the anchor position at the left
    907             // basepoint of the tetx. This is the default anchor point for
    908             // TTF text.
    909 
    910             if( $this->text_valign != 'basepoint' ) {
    911                 // Align x,y ot lower left corner of bbox
    912                
    913 
    914                 if( $this->text_halign=='right' ) {
    915                     $x -= $width;
    916                     $x -= $bbox[0];
    917                 }
    918                 elseif( $this->text_halign=='center' ) {
    919                     $x -= $width/2;
    920                     $x -= $bbox[0];
    921                 }
    922                 elseif( $this->text_halign=='baseline' ) {
    923                     // This is only support for text at 90 degree !!
    924                     // Do nothing the text is drawn at baseline by default
    925                 }
    926 
    927                 if( $this->text_valign=='top' ) {
    928                     $y -= $bbox[1]; // Adjust to bottom of text
    929                     $y += $height;
    930                 }
    931                 elseif( $this->text_valign=='center' ) {
    932                     $y -= $bbox[1]; // Adjust to bottom of text
    933                     $y += $height/2;
    934                 }
    935                 elseif( $this->text_valign=='baseline' ) {
    936                     // This is only support for text at 0 degree !!
    937                     // Do nothing the text is drawn at baseline by default
    938                 }
    939             }
    940             ImageTTFText ($this->img, $this->font_size, $dir, $x, $y,
    941                           $this->current_color,$this->font_file,$txt);
    942 
    943             // Calculate and return the co-ordinates for the bounding box
    944             $box = $this->imagettfbbox_fixed($this->font_size,$dir,$this->font_file,$txt);
    945             $p1 = array();
    946 
    947             for($i=0; $i < 4; ++$i) {
    948                 $p1[] = round($box[$i*2]+$x);
    949                 $p1[] = round($box[$i*2+1]+$y);
    950             }
    951             $aBoundingBox = $p1;
    952 
    953             // Debugging code to highlight the bonding box and bounding rectangle
    954             // For text at 0 degrees the bounding box and bounding rectangle are the
    955             // same
    956             if( $debug ) {
    957             // Draw the bounding rectangle and the bounding box
    958 
    959                 $p = array();
    960                 $p1 = array();
    961 
    962                 for($i=0; $i < 4; ++$i) {
    963                     $p[] =  $bbox[$i*2]+$x ;
    964                     $p[] =  $bbox[$i*2+1]+$y;
    965                     $p1[] = $box[$i*2]+$x ;
    966                     $p1[] = $box[$i*2+1]+$y ;
    967                 }
    968 
    969                 // Draw bounding box
    970                 $this->PushColor('green');
    971                 $this->Polygon($p1,true);
    972                 $this->PopColor();
    973 
    974                 // Draw bounding rectangle
    975                 $this->PushColor('darkgreen');
    976                 $this->Polygon($p,true);
    977                 $this->PopColor();
    978 
    979                 // Draw a cross at the anchor point
    980                 $this->PushColor('red');
    981                 $this->Line($ox-15,$oy,$ox+15,$oy);
    982                 $this->Line($ox,$oy-15,$ox,$oy+15);
    983                 $this->PopColor();
    984             }
    985         }
    986         else {
    987             // Format a text paragraph
    988             $fh=$this->GetFontHeight();
    989 
    990             // Line margin is 25% of font height
    991             $linemargin=round($fh*$ConstLineSpacing);
    992             $fh += $linemargin;
    993             $w=$this->GetTextWidth($txt);
    994 
    995             $y -= $linemargin/2;
    996             $tmp = preg_split('/\n/',$txt);
    997             $nl = count($tmp);
    998             $h = $nl * $fh;
    999 
    1000             if( $this->text_halign=='right') {
    1001                 $x -= $dir==0 ? $w : $h;
    1002             }
    1003             elseif( $this->text_halign=='center' ) {
    1004                 $x -= $dir==0 ? $w/2 : $h/2;
    1005             }
    1006 
    1007             if( $this->text_valign=='top' ) {
    1008                 $y += $dir==0 ? $h : $w;
    1009             }
    1010             elseif( $this->text_valign=='center' ) {
    1011                 $y += $dir==0 ? $h/2 : $w/2;
    1012             }
    1013 
    1014             // Here comes a tricky bit.
    1015             // Since we have to give the position for the string at the
    1016             // baseline this means thaht text will move slightly up
    1017             // and down depending on any of it's character descend below
    1018             // the baseline, for example a 'g'. To adjust the Y-position
    1019             // we therefore adjust the text with the baseline Y-offset
    1020             // as used for the current font and size. This will keep the
    1021             // baseline at a fixed positoned disregarding the actual
    1022             // characters in the string.
    1023             $standardbox = $this->GetTTFBBox('Gg',$dir);
    1024             $yadj = $standardbox[1];
    1025             $xadj = $standardbox[0];
    1026             $aBoundingBox = array();
    1027             for($i=0; $i < $nl; ++$i) {
    1028                 $wl = $this->GetTextWidth($tmp[$i]);
    1029                 $bbox = $this->GetTTFBBox($tmp[$i],$dir);
    1030                 if( $paragraph_align=='left' ) {
    1031                     $xl = $x;
    1032                 }
    1033                 elseif( $paragraph_align=='right' ) {
    1034                     $xl = $x + ($w-$wl);
    1035                 }
    1036                 else {
    1037                     // Center
    1038                     $xl = $x + $w/2 - $wl/2 ;
    1039                 }
    1040 
    1041                 // In theory we should adjust with full pre-lead to get the lines
    1042                 // lined up but this doesn't look good so therfore we only adjust with
    1043                 // half th pre-lead
    1044                 $xl -= $bbox[0]/2;
    1045                 $yl = $y - $yadj;
    1046                 //$xl = $xl- $xadj;
    1047                 ImageTTFText($this->img, $this->font_size, $dir, $xl, $yl-($h-$fh)+$fh*$i,
    1048                              $this->current_color,$this->font_file,$tmp[$i]);
    1049 
    1050                // echo "xl=$xl,".$tmp[$i]." <br>";
    1051                 if( $debug  ) {
    1052                     // Draw the bounding rectangle around each line
    1053                     $box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$tmp[$i]);
    1054                     $p = array();
    1055                     for($j=0; $j < 4; ++$j) {
    1056                         $p[] = $bbox[$j*2]+$xl;
    1057                         $p[] = $bbox[$j*2+1]+$yl-($h-$fh)+$fh*$i;
    1058                     }
    1059 
    1060                     // Draw bounding rectangle
    1061                     $this->PushColor('darkgreen');
    1062                     $this->Polygon($p,true);
    1063                     $this->PopColor();
    1064                 }
    1065             }
    1066 
    1067             // Get the bounding box
    1068             $bbox = $this->GetBBoxTTF($txt,$dir);
    1069             for($j=0; $j < 4; ++$j) {
    1070                 $bbox[$j*2]+= round($x);
    1071                 $bbox[$j*2+1]+= round($y - ($h-$fh) - $yadj);
    1072             }
    1073             $aBoundingBox = $bbox;
    1074 
    1075             if( $debug ) {
    1076                 // Draw a cross at the anchor point
    1077                 $this->PushColor('red');
    1078                 $this->Line($ox-25,$oy,$ox+25,$oy);
    1079                 $this->Line($ox,$oy-25,$ox,$oy+25);
    1080                 $this->PopColor();
    1081             }
    1082 
    1083         }
    1084     }
    1085 
     649        }
     650        else {
     651            // Format a text paragraph
     652            $fh=$this->GetFontHeight();
     653
     654            // Line margin is 25% of font height
     655            $linemargin=round($fh*$ConstLineSpacing);
     656            $fh += $linemargin;
     657            $w=$this->GetTextWidth($txt);
     658
     659            $y -= $linemargin/2;
     660            $tmp = split("\n",$txt);
     661            $nl = count($tmp);
     662            $h = $nl * $fh;
     663
     664            if( $this->text_halign=="right")                           
     665                $x -= $dir==0 ? $w : $h;
     666            elseif( $this->text_halign=="center" ) {
     667                $x -= $dir==0 ? $w/2 : $h/2;
     668            }
     669           
     670            if( $this->text_valign=="top" )
     671                $y +=   $dir==0 ? $h : $w;
     672            elseif( $this->text_valign=="center" )                             
     673                $y +=   $dir==0 ? $h/2 : $w/2;
     674
     675            // Here comes a tricky bit.
     676            // Since we have to give the position for the string at the
     677            // baseline this means thaht text will move slightly up
     678            // and down depending on any of it's character descend below
     679            // the baseline, for example a 'g'. To adjust the Y-position
     680            // we therefore adjust the text with the baseline Y-offset
     681            // as used for the current font and size. This will keep the
     682            // baseline at a fixed positoned disregarding the actual
     683            // characters in the string.
     684            $standardbox = $this->GetTTFBBox('Gg',$dir);
     685            $yadj = $standardbox[1];
     686            $xadj = $standardbox[0];
     687            $aBoundingBox = array();
     688            for($i=0; $i < $nl; ++$i) {
     689                $wl = $this->GetTextWidth($tmp[$i]);
     690                $bbox = $this->GetTTFBBox($tmp[$i],$dir);
     691                if( $paragraph_align=="left" ) {
     692                    $xl = $x;
     693                }
     694                elseif( $paragraph_align=="right" ) {
     695                    $xl = $x + ($w-$wl);
     696                }
     697                else {
     698                    // Center
     699                    $xl = $x + $w/2 - $wl/2 ;
     700                }
     701
     702                $xl -= $bbox[0];
     703                $yl = $y - $yadj;
     704                $xl = $xl - $xadj;
     705                ImageTTFText ($this->img, $this->font_size, $dir,
     706                              $xl, $yl-($h-$fh)+$fh*$i,
     707                              $this->current_color,$this->font_file,$tmp[$i]);
     708
     709                if( $debug  ) {
     710                    // Draw the bounding rectangle around each line
     711                    $box=@ImageTTFBBox($this->font_size,$dir,$this->font_file,$tmp[$i]);
     712                    $p = array();
     713                    for($j=0; $j < 4; ++$j) {
     714                        $p[] = $bbox[$j*2]+$xl;
     715                        $p[] = $bbox[$j*2+1]+$yl-($h-$fh)+$fh*$i;
     716                    }
     717                   
     718                    // Draw bounding rectangle
     719                    $this->PushColor('darkgreen');
     720                    $this->Polygon($p,true);
     721                    $this->PopColor();
     722                }
     723            }
     724
     725            // Get the bounding box
     726            $bbox = $this->GetBBoxTTF($txt,$dir);
     727            for($j=0; $j < 4; ++$j) {
     728                $bbox[$j*2]+= round($x);
     729                $bbox[$j*2+1]+= round($y - ($h-$fh) - $yadj);
     730            }
     731            $aBoundingBox = $bbox;
     732
     733            if( $debug ) {     
     734                // Draw a cross at the anchor point
     735                $this->PushColor('red');
     736                $this->Line($ox-25,$oy,$ox+25,$oy);
     737                $this->Line($ox,$oy-25,$ox,$oy+25);
     738                $this->PopColor();
     739            }
     740
     741        }
     742    }
     743       
    1086744    function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) {
    1087745
    1088         $x = round($x);
    1089         $y = round($y);
    1090 
    1091         // Do special language encoding
    1092         $txt = $this->langconv->Convert($txt,$this->font_family);
    1093 
    1094         if( !is_numeric($dir) ) {
    1095             JpGraphError::RaiseL(25094);//(" Direction for text most be given as an angle between 0 and 90.");
    1096         }
    1097 
    1098         if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) {
    1099             $this->_StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug);
    1100         }
    1101         elseif( $this->font_family >= _FIRST_FONT && $this->font_family <= _LAST_FONT)  {
    1102             $this->_StrokeTTF($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug);
    1103         }
    1104         else {
    1105             JpGraphError::RaiseL(25095);//(" Unknown font font family specification. ");
    1106         }
    1107         return $boundingbox;
    1108     }
    1109 
     746        $x = round($x);
     747        $y = round($y);
     748
     749        // Do special language encoding
     750        $txt = $this->langconv->Convert($txt,$this->font_family);
     751
     752        if( !is_numeric($dir) )
     753            JpGraphError::RaiseL(25094);//(" Direction for text most be given as an angle between 0 and 90.");
     754                       
     755        if( $this->font_family >= FF_FONT0 && $this->font_family <= FF_FONT2+1) {       
     756            $this->_StrokeBuiltinFont($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug);
     757        }
     758        elseif($this->font_family >= _FIRST_FONT && $this->font_family <= _LAST_FONT)  {
     759            $this->_StrokeTTF($x,$y,$txt,$dir,$paragraph_align,$boundingbox,$debug);
     760        }
     761        else
     762            JpGraphError::RaiseL(25095);//(" Unknown font font family specification. ");
     763        return $boundingbox;
     764    }
     765       
    1110766    function SetMargin($lm,$rm,$tm,$bm) {
    1111 
    1112         $this->left_margin=$lm;
    1113         $this->right_margin=$rm;
    1114         $this->top_margin=$tm;
    1115         $this->bottom_margin=$bm;
    1116 
    1117         $this->plotwidth  = $this->width  - $this->left_margin - $this->right_margin;
    1118         $this->plotheight = $this->height - $this->top_margin  - $this->bottom_margin;
    1119 
    1120         if( $this->width  > 0 && $this->height > 0 ) {
    1121             if( $this->plotwidth < 0  || $this->plotheight < 0 ) {
    1122                 JpGraphError::RaiseL(25130, $this->plotwidth, $this->plotheight);
    1123                 //JpGraphError::raise("To small plot area. ($lm,$rm,$tm,$bm : $this->plotwidth x $this->plotheight). With the given image size and margins there is to little space left for the plot. Increase the plot size or reduce the margins.");
    1124             }
    1125         }
     767        $this->left_margin=$lm;
     768        $this->right_margin=$rm;
     769        $this->top_margin=$tm;
     770        $this->bottom_margin=$bm;
     771        $this->plotwidth=$this->width - $this->left_margin-$this->right_margin ;
     772        $this->plotheight=$this->height - $this->top_margin-$this->bottom_margin ;
     773        if( $this->width  > 0 && $this->height > 0 ) {
     774            if( $this->plotwidth < 0  || $this->plotheight < 0 )
     775                JpGraphError::raise("To small plot area. ($lm,$rm,$tm,$bm : $this->plotwidth x $this->plotheight). With the given image size and margins there is to little space left for the plot. Increase the plot size or reduce the margins.");
     776        }
    1126777    }
    1127778
    1128779    function SetTransparent($color) {
    1129         imagecolortransparent ($this->img,$this->rgb->allocate($color));
    1130     }
    1131 
     780        imagecolortransparent ($this->img,$this->rgb->allocate($color));
     781    }
     782       
    1132783    function SetColor($color,$aAlpha=0) {
    1133         $this->current_color_name = $color;
    1134         $this->current_color=$this->rgb->allocate($color,$aAlpha);
    1135         if( $this->current_color == -1 ) {
    1136             $tc=imagecolorstotal($this->img);
    1137             JpGraphError::RaiseL(25096);
    1138             //("Can't allocate any more colors. Image has already allocated maximum of <b>$tc colors</b>. This might happen if you have anti-aliasing turned on together with a background image or perhaps gradient fill since this requires many, many colors. Try to turn off anti-aliasing. If there is still a problem try downgrading the quality of the background image to use a smaller pallete to leave some entries for your graphs. You should try to limit the number of colors in your background image to 64. If there is still problem set the constant DEFINE(\"USE_APPROX_COLORS\",true); in jpgraph.php This will use approximative colors when the palette is full. Unfortunately there is not much JpGraph can do about this since the palette size is a limitation of current graphic format and what the underlying GD library suppports.");
    1139         }
    1140         return $this->current_color;
    1141     }
    1142 
     784        $this->current_color_name = $color;
     785        $this->current_color=$this->rgb->allocate($color,$aAlpha);
     786        if( $this->current_color == -1 ) {
     787            $tc=imagecolorstotal($this->img);
     788            JpGraphError::RaiseL(25096);
     789//("Can't allocate any more colors. Image has already allocated maximum of <b>$tc colors</b>. This might happen if you have anti-aliasing turned on together with a background image or perhaps gradient fill since this requires many, many colors. Try to turn off anti-aliasing. If there is still a problem try downgrading the quality of the background image to use a smaller pallete to leave some entries for your graphs. You should try to limit the number of colors in your background image to 64. If there is still problem set the constant DEFINE(\"USE_APPROX_COLORS\",true); in jpgraph.php This will use approximative colors when the palette is full. Unfortunately there is not much JpGraph can do about this since the palette size is a limitation of current graphic format and what the underlying GD library suppports.");
     790        }
     791        return $this->current_color;
     792    }
     793       
    1143794    function PushColor($color) {
    1144         if( $color != "" ) {
    1145             $this->colorstack[$this->colorstackidx]=$this->current_color_name;
    1146             $this->colorstack[$this->colorstackidx+1]=$this->current_color;
    1147             $this->colorstackidx+=2;
    1148             $this->SetColor($color);
    1149         }
    1150         else {
    1151             JpGraphError::RaiseL(25097);//("Color specified as empty string in PushColor().");
    1152         }
    1153     }
    1154 
     795        if( $color != "" ) {
     796            $this->colorstack[$this->colorstackidx]=$this->current_color_name;
     797            $this->colorstack[$this->colorstackidx+1]=$this->current_color;
     798            $this->colorstackidx+=2;
     799            $this->SetColor($color);
     800        }
     801        else {
     802            JpGraphError::RaiseL(25097);//("Color specified as empty string in PushColor().");
     803        }
     804    }
     805       
    1155806    function PopColor() {
    1156         if( $this->colorstackidx < 1 ) {
    1157             JpGraphError::RaiseL(25098);//(" Negative Color stack index. Unmatched call to PopColor()");
    1158         }
    1159         $this->current_color=$this->colorstack[--$this->colorstackidx];
    1160         $this->current_color_name=$this->colorstack[--$this->colorstackidx];
    1161     }
    1162 
    1163 
     807        if($this->colorstackidx<1)
     808            JpGraphError::RaiseL(25098);//(" Negative Color stack index. Unmatched call to PopColor()");
     809        $this->current_color=$this->colorstack[--$this->colorstackidx];
     810        $this->current_color_name=$this->colorstack[--$this->colorstackidx];
     811    }
     812       
     813       
    1164814    function SetLineWeight($weight) {
    1165         $old = $this->line_weight;
    1166         imagesetthickness($this->img,$weight);
    1167         $this->line_weight = $weight;
    1168         return $old;
    1169     }
    1170 
     815        imagesetthickness($this->img,$weight);
     816        $this->line_weight = $weight;
     817    }
     818       
    1171819    function SetStartPoint($x,$y) {
    1172         $this->lastx=round($x);
    1173         $this->lasty=round($y);
    1174     }
    1175 
     820        $this->lastx=round($x);
     821        $this->lasty=round($y);
     822    }
     823       
    1176824    function Arc($cx,$cy,$w,$h,$s,$e) {
    1177         // GD Arc doesn't like negative angles
    1178         while( $s < 0) $s += 360;
    1179         while( $e < 0) $e += 360;
    1180         imagearc($this->img,round($cx),round($cy),round($w),round($h),$s,$e,$this->current_color);
    1181     }
    1182 
     825        // GD Arc doesn't like negative angles
     826        while( $s < 0) $s += 360;
     827        while( $e < 0) $e += 360;
     828       
     829        imagearc($this->img,round($cx),round($cy),round($w),round($h),
     830                 $s,$e,$this->current_color);
     831    }
     832   
    1183833    function FilledArc($xc,$yc,$w,$h,$s,$e,$style='') {
    1184         $s = round($s);
    1185         $e = round($e);
    1186         while( $s < 0 ) $s += 360;
    1187         while( $e < 0 ) $e += 360;
    1188         if( $style=='' )
    1189         $style=IMG_ARC_PIE;
    1190         if( abs($s-$e) > 0 ) {
    1191             imagefilledarc($this->img,round($xc),round($yc),round($w),round($h),$s,$e,$this->current_color,$style);
    1192 //            $this->DrawImageSmoothArc($this->img,round($xc),round($yc),round($w),round($h),$s,$e,$this->current_color,$style);
    1193         }
     834        while( $s < 0 ) $s += 360;
     835        while( $e < 0 ) $e += 360;
     836        if( $style=='' )
     837            $style=IMG_ARC_PIE;
     838        if( abs($s-$e) > 0.001 ) {
     839            imagefilledarc($this->img,round($xc),round($yc),round($w),round($h),
     840                           round($s),round($e),$this->current_color,$style);
     841        }
    1194842    }
    1195843
    1196844    function FilledCakeSlice($cx,$cy,$w,$h,$s,$e) {
    1197         $this->CakeSlice($cx,$cy,$w,$h,$s,$e,$this->current_color_name);
     845        $this->CakeSlice($cx,$cy,$w,$h,$s,$e,$this->current_color_name);
    1198846    }
    1199847
    1200848    function CakeSlice($xc,$yc,$w,$h,$s,$e,$fillcolor="",$arccolor="") {
    1201         $s = round($s); $e = round($e);
    1202         $w = round($w); $h = round($h);
    1203         $xc = round($xc); $yc = round($yc);
    1204         if( $s == $e ) {
    1205             // A full circle. We draw this a plain circle
    1206             $this->PushColor($fillcolor);
    1207             imagefilledellipse($this->img,$xc,$yc,2*$w,2*$h,$this->current_color);
    1208 
    1209             // If antialiasing is used then we often don't have any color no the surrounding
    1210             // arc. So, we need to check for this special case so we don't send an empty
    1211             // color to the push function. In this case we use the fill color for the arc as well
    1212             if( $arccolor != '' ) {
    1213                 $this->PopColor();
    1214                 $this->PushColor($arccolor);
    1215             }
    1216             imageellipse($this->img,$xc,$yc,2*$w,2*$h,$this->current_color);
    1217             $this->Line($xc,$yc,cos($s*M_PI/180)*$w+$xc,$yc+sin($s*M_PI/180)*$h);
    1218             $this->PopColor();
    1219         }
    1220         else {
    1221             $this->PushColor($fillcolor);
    1222             $this->FilledArc($xc,$yc,2*$w,2*$h,$s,$e);
    1223             $this->PopColor();
    1224             if( $arccolor != "" ) {
    1225                 $this->PushColor($arccolor);
    1226                 // We add 2 pixels to make the Arc() better aligned with
    1227                 // the filled arc.
    1228                 imagefilledarc($this->img,$xc,$yc,2*$w,2*$h,$s,$e,$this->current_color,IMG_ARC_NOFILL | IMG_ARC_EDGED ) ;
    1229                 $this->PopColor();
    1230             }
    1231         }
     849        $s = round($s); $e = round($e);
     850        $w = round($w); $h = round($h);
     851        $xc = round($xc); $yc = round($yc);
     852        if( $s ==$e ) {
     853            // A full circle. We draw this a plain circle
     854            $this->PushColor($fillcolor);
     855            imagefilledellipse($this->img,$xc,$yc,2*$w,2*$h,$this->current_color);
     856            $this->PopColor();
     857            $this->PushColor($arccolor);
     858            imageellipse($this->img,$xc,$yc,2*$w,2*$h,$this->current_color);
     859            $this->Line($xc,$yc,cos($s*M_PI/180)*$w+$xc,$yc+sin($s*M_PI/180)*$h);
     860            $this->PopColor();
     861        }
     862        else {
     863            $this->PushColor($fillcolor);
     864            $this->FilledArc($xc,$yc,2*$w,2*$h,$s,$e);
     865            $this->PopColor();
     866            if( $arccolor != "" ) {
     867                $this->PushColor($arccolor);
     868                // We add 2 pixels to make the Arc() better aligned with
     869                // the filled arc.
     870                imagefilledarc($this->img,$xc,$yc,2*$w,2*$h,$s,$e,$this->current_color,IMG_ARC_NOFILL | IMG_ARC_EDGED ) ;
     871                $this->PopColor();
     872            }
     873        }
    1232874    }
    1233875
    1234876    function Ellipse($xc,$yc,$w,$h) {
    1235         $this->Arc($xc,$yc,$w,$h,0,360);
    1236     }
    1237 
     877        $this->Arc($xc,$yc,$w,$h,0,360);
     878    }
     879                       
    1238880    function Circle($xc,$yc,$r) {
    1239         imageellipse($this->img,round($xc),round($yc),$r*2,$r*2,$this->current_color);
    1240 //        $this->DrawImageSmoothArc($this->img,round($xc),round($yc),$r*2+1,$r*2+1,0,360,$this->current_color);
    1241 //        $this->imageSmoothCircle($this->img, round($xc),round($yc), $r*2+1, $this->current_color);
    1242     }
    1243 
     881        imageellipse($this->img,round($xc),round($yc),$r*2,$r*2,$this->current_color);
     882    }
     883       
    1244884    function FilledCircle($xc,$yc,$r) {
    1245         imagefilledellipse($this->img,round($xc),round($yc),2*$r,2*$r,$this->current_color);
    1246 //        $this->DrawImageSmoothArc($this->img, round($xc), round($yc), 2*$r, 2*$r, 0, 360, $this->current_color);
    1247     }
    1248 
     885        imagefilledellipse($this->img,round($xc),round($yc),2*$r,2*$r,$this->current_color);
     886    }
     887       
    1249888    // Linear Color InterPolation
    1250889    function lip($f,$t,$p) {
    1251         $p = round($p,1);
    1252         $r = $f[0] + ($t[0]-$f[0])*$p;
    1253         $g = $f[1] + ($t[1]-$f[1])*$p;
    1254         $b = $f[2] + ($t[2]-$f[2])*$p;
    1255         return array($r,$g,$b);
     890        $p = round($p,1);
     891        $r = $f[0] + ($t[0]-$f[0])*$p;
     892        $g = $f[1] + ($t[1]-$f[1])*$p;
     893        $b = $f[2] + ($t[2]-$f[2])*$p;
     894        return array($r,$g,$b);
    1256895    }
    1257896
    1258897    // Set line style dashed, dotted etc
    1259898    function SetLineStyle($s) {
    1260         if( is_numeric($s) ) {
    1261             if( $s<1 || $s>4 ) {
    1262                 JpGraphError::RaiseL(25101,$s);//(" Illegal numeric argument to SetLineStyle(): ($s)");
    1263             }
    1264         }
    1265         elseif( is_string($s) ) {
    1266             if( $s == "solid" ) $s=1;
    1267             elseif( $s == "dotted" ) $s=2;
    1268             elseif( $s == "dashed" ) $s=3;
    1269             elseif( $s == "longdashed" ) $s=4;
    1270             else {
    1271                 JpGraphError::RaiseL(25102,$s);//(" Illegal string argument to SetLineStyle(): $s");
    1272             }
    1273         }
    1274         else {
    1275             JpGraphError::RaiseL(25103,$s);//(" Illegal argument to SetLineStyle $s");
    1276         }
    1277         $old = $this->line_style;
    1278         $this->line_style=$s;
    1279         return $old;
    1280     }
    1281 
     899        if( is_numeric($s) ) {
     900            if( $s<1 || $s>4 )
     901                JpGraphError::RaiseL(25101,$s);//(" Illegal numeric argument to SetLineStyle(): ($s)");
     902        }
     903        elseif( is_string($s) ) {
     904            if( $s == "solid" ) $s=1;
     905            elseif( $s == "dotted" ) $s=2;
     906            elseif( $s == "dashed" ) $s=3;
     907            elseif( $s == "longdashed" ) $s=4;
     908            else JpGraphError::RaiseL(25102,$s);//(" Illegal string argument to SetLineStyle(): $s");
     909        }
     910        else {
     911            JpGraphError::RaiseL(25103,$s);//(" Illegal argument to SetLineStyle $s");
     912        }
     913        $old = $this->line_style;
     914        $this->line_style=$s;
     915        return $old;
     916    }
     917       
    1282918    // Same as Line but take the line_style into account
    1283     function StyleLine($x1,$y1,$x2,$y2,$aStyle='', $from_grid_class = false) {
    1284         if( $this->line_weight <= 0 ) return;
    1285 
    1286         if( $aStyle === '' ) {
    1287             $aStyle = $this->line_style;
    1288         }
    1289 
    1290         $dashed_line_method = 'DashedLine';
    1291         if ($from_grid_class) {
    1292             $dashed_line_method = 'DashedLineForGrid';
    1293         }
    1294 
    1295         // Add error check since dashed line will only work if anti-alias is disabled
    1296         // this is a limitation in GD
    1297 
    1298         if( $aStyle == 1 ) {
    1299             // Solid style. We can handle anti-aliasing for this
    1300             $this->Line($x1,$y1,$x2,$y2);
    1301         }
    1302         else {
    1303             // Since the GD routines doesn't handle AA for styled line
    1304             // we have no option than to turn it off to get any lines at
    1305             // all if the weight > 1
    1306             $oldaa = $this->GetAntiAliasing();
    1307             if( $oldaa && $this->line_weight > 1 ) {
    1308                  $this->SetAntiAliasing(false);
    1309             }
    1310 
    1311             switch( $aStyle ) {
    1312                 case 2: // Dotted
    1313                     $this->$dashed_line_method($x1,$y1,$x2,$y2,2,6);
    1314                     break;
    1315                 case 3: // Dashed
    1316                     $this->$dashed_line_method($x1,$y1,$x2,$y2,5,9);
    1317                     break;
    1318                 case 4: // Longdashes
    1319                     $this->$dashed_line_method($x1,$y1,$x2,$y2,9,13);
    1320                     break;
    1321                 default:
    1322                     JpGraphError::RaiseL(25104,$this->line_style);//(" Unknown line style: $this->line_style ");
    1323                     break;
    1324             }
    1325             if( $oldaa ) {
    1326                 $this->SetAntiAliasing(true);
    1327             }
    1328         }
    1329     }
    1330 
     919    function StyleLine($x1,$y1,$x2,$y2,$aStyle='') {
     920        if( $this->line_weight <= 0 )
     921            return;
     922
     923        if( $aStyle === '' ) {
     924            $aStyle = $this->line_style;
     925        }
     926
     927        // Add error check since dashed line will only work if anti-alias is disabled
     928        // this is a limitation in GD
     929
     930        switch( $aStyle ) {
     931            case 1:// Solid
     932                $this->Line($x1,$y1,$x2,$y2);
     933                break;
     934            case 2: // Dotted
     935                $this->DashedLine($x1,$y1,$x2,$y2,2,6);
     936                break;
     937            case 3: // Dashed
     938                $this->DashedLine($x1,$y1,$x2,$y2,5,9);
     939                break;
     940            case 4: // Longdashes
     941                $this->DashedLine($x1,$y1,$x2,$y2,9,13);
     942                break;
     943            default:
     944                JpGraphError::RaiseL(25104,$this->line_style);//(" Unknown line style: $this->line_style ");
     945                break;
     946        }
     947    }
     948       
    1331949    function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) {
    1332950
    1333         if( $this->line_weight <= 0 ) return;
    1334 
    1335         // Add error check to make sure anti-alias is not enabled.
    1336         // Dashed line does not work with anti-alias enabled. This
    1337         // is a limitation in GD.
    1338         if( $this->use_anti_aliasing ) {
    1339 //            JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.
    1340         }
    1341        
    1342         $x1 = round($x1);
    1343         $x2 = round($x2);
    1344         $y1 = round($y1);
    1345         $y2 = round($y2);
    1346 
    1347         $dash_length *= SUPERSAMPLING_SCALE;
    1348         $dash_space  *= SUPERSAMPLING_SCALE;
    1349 
    1350         $style = array_fill(0,$dash_length,$this->current_color);
    1351         $style = array_pad($style,$dash_space,IMG_COLOR_TRANSPARENT);
    1352         imagesetstyle($this->img, $style);
    1353         imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
    1354 
    1355         $this->lastx = $x2;
    1356         $this->lasty = $y2;
    1357     }
    1358 
    1359     function DashedLineForGrid($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) {
    1360 
    1361         if( $this->line_weight <= 0 ) return;
    1362 
    1363         // Add error check to make sure anti-alias is not enabled.
    1364         // Dashed line does not work with anti-alias enabled. This
    1365         // is a limitation in GD.
    1366         if( $this->use_anti_aliasing ) {
    1367 //            JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.
    1368         }
    1369        
    1370         $x1 = round($x1);
    1371         $x2 = round($x2);
    1372         $y1 = round($y1);
    1373         $y2 = round($y2);
    1374        
    1375         /*
    1376         $dash_length *= $this->scale;
    1377         $dash_space  *= $this->scale;
    1378         */
    1379 
    1380         $dash_length = 2;
    1381         $dash_length = 4;
    1382         imagesetthickness($this->img, 1);
    1383         $style = array_fill(0,$dash_length, $this->current_color); //hexdec('CCCCCC'));
    1384         $style = array_pad($style,$dash_space,IMG_COLOR_TRANSPARENT);
    1385         imagesetstyle($this->img, $style);
    1386         imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
    1387 
    1388         $this->lastx = $x2;
    1389         $this->lasty = $y2;
    1390     }
     951        if( $this->line_weight <= 0 )
     952            return;
     953
     954        // Add error check to make sure anti-alias is not enabled.
     955        // Dashed line does not work with anti-alias enabled. This
     956        // is a limitation in GD.
     957        if( $this->use_anti_aliasing ) {
     958            JpGraphError::RaiseL(25129); // Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.
     959        }
     960       
     961
     962        $x1 = round($x1);
     963        $x2 = round($x2);
     964        $y1 = round($y1);
     965        $y2 = round($y2);
     966
     967        $style = array_fill(0,$dash_length,$this->current_color);
     968        $style = array_pad($style,$dash_space,IMG_COLOR_TRANSPARENT);
     969        imagesetstyle($this->img, $style);
     970        imageline($this->img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED);
     971        $this->lastx=$x2; $this->lasty=$y2;             
     972    }
    1391973
    1392974    function Line($x1,$y1,$x2,$y2) {
    1393975
    1394         if( $this->line_weight <= 0 ) return;
    1395 
    1396         $x1 = round($x1);
    1397         $x2 = round($x2);
    1398         $y1 = round($y1);
    1399         $y2 = round($y2);
    1400 
    1401         imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color);
    1402 //        $this->DrawLine($this->img, $x1, $y1, $x2, $y2, $this->line_weight, $this->current_color);
    1403         $this->lastx=$x2;
    1404         $this->lasty=$y2;
     976        if( $this->line_weight <= 0 )
     977            return;
     978
     979        $x1 = round($x1);
     980        $x2 = round($x2);
     981        $y1 = round($y1);
     982        $y2 = round($y2);
     983
     984        imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color);
     985        $this->lastx=$x2; $this->lasty=$y2;             
    1405986    }
    1406987
    1407988    function Polygon($p,$closed=FALSE,$fast=FALSE) {
    1408989
    1409         if( $this->line_weight <= 0 ) return;
    1410 
    1411         $n=count($p);
    1412         $oldx = $p[0];
    1413         $oldy = $p[1];
    1414         if( $fast ) {
    1415             for( $i=2; $i < $n; $i+=2 ) {
    1416                 imageline($this->img,$oldx,$oldy,$p[$i],$p[$i+1],$this->current_color);
    1417                 $oldx = $p[$i];
    1418                 $oldy = $p[$i+1];
    1419             }
    1420             if( $closed ) {
    1421                 imageline($this->img,$p[$n*2-2],$p[$n*2-1],$p[0],$p[1],$this->current_color);
    1422             }
    1423         }
    1424         else {
    1425             for( $i=2; $i < $n; $i+=2 ) {
    1426                 $this->StyleLine($oldx,$oldy,$p[$i],$p[$i+1]);
    1427                 $oldx = $p[$i];
    1428                 $oldy = $p[$i+1];
    1429             }
    1430             if( $closed ) {
    1431                 $this->StyleLine($oldx,$oldy,$p[0],$p[1]);
    1432             }
    1433         }
    1434     }
    1435 
     990        if( $this->line_weight <= 0 )
     991            return;
     992
     993        $n=count($p);
     994        $oldx = $p[0];
     995        $oldy = $p[1];
     996        if( $fast ) {
     997            for( $i=2; $i < $n; $i+=2 ) {
     998                imageline($this->img,$oldx,$oldy,$p[$i],$p[$i+1],$this->current_color);
     999                $oldx = $p[$i];
     1000                $oldy = $p[$i+1];
     1001            }
     1002            if( $closed ) {
     1003                imageline($this->img,$p[$n*2-2],$p[$n*2-1],$p[0],$p[1],$this->current_color);
     1004            }
     1005        }
     1006        else {
     1007            for( $i=2; $i < $n; $i+=2 ) {
     1008                $this->StyleLine($oldx,$oldy,$p[$i],$p[$i+1]);
     1009                $oldx = $p[$i];
     1010                $oldy = $p[$i+1];
     1011            }
     1012            if( $closed )
     1013                $this->StyleLine($oldx,$oldy,$p[0],$p[1]);
     1014        }
     1015    }
     1016       
    14361017    function FilledPolygon($pts) {
    1437         $n=count($pts);
    1438         if( $n == 0 ) {
    1439             JpGraphError::RaiseL(25105);//('NULL data specified for a filled polygon. Check that your data is not NULL.');
    1440         }
    1441         for($i=0; $i < $n; ++$i) {
    1442             $pts[$i] = round($pts[$i]);
    1443         }
    1444         $old = $this->line_weight;
    1445         imagesetthickness($this->img,1);
    1446         imagefilledpolygon($this->img,$pts,count($pts)/2,$this->current_color);
    1447         $this->line_weight = $old;
    1448         imagesetthickness($this->img,$old);
    1449     }
    1450 
     1018        $n=count($pts);
     1019        if( $n == 0 ) {
     1020            JpGraphError::RaiseL(25105);//('NULL data specified for a filled polygon. Check that your data is not NULL.');
     1021        }
     1022        for($i=0; $i < $n; ++$i)
     1023            $pts[$i] = round($pts[$i]);
     1024        imagefilledpolygon($this->img,$pts,count($pts)/2,$this->current_color);
     1025    }
     1026       
    14511027    function Rectangle($xl,$yu,$xr,$yl) {
    1452         $this->Polygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl,$xl,$yu));
    1453     }
    1454 
     1028        $this->Polygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl,$xl,$yu));
     1029    }
     1030       
    14551031    function FilledRectangle($xl,$yu,$xr,$yl) {
    1456         $this->FilledPolygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl));
     1032        $this->FilledPolygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl));
    14571033    }
    14581034
    14591035    function FilledRectangle2($xl,$yu,$xr,$yl,$color1,$color2,$style=1) {
    1460         // Fill a rectangle with lines of two colors
    1461         if( $style===1 ) {
    1462             // Horizontal stripe
    1463             if( $yl < $yu ) {
    1464                 $t = $yl; $yl=$yu; $yu=$t;
    1465             }
    1466             for( $y=$yu; $y <= $yl; ++$y) {
    1467                 $this->SetColor($color1);
    1468                 $this->Line($xl,$y,$xr,$y);
    1469                 ++$y;
    1470                 $this->SetColor($color2);
    1471                 $this->Line($xl,$y,$xr,$y);
    1472             }
    1473         }
    1474         else {
    1475             if( $xl < $xl ) {
    1476                 $t = $xl; $xl=$xr; $xr=$t;
    1477             }
    1478             for( $x=$xl; $x <= $xr; ++$x) {
    1479                 $this->SetColor($color1);
    1480                 $this->Line($x,$yu,$x,$yl);
    1481                 ++$x;
    1482                 $this->SetColor($color2);
    1483                 $this->Line($x,$yu,$x,$yl);
    1484             }
    1485         }
    1486     }
    1487 
    1488     function ShadowRectangle($xl,$yu,$xr,$yl,$fcolor=false,$shadow_width=4,$shadow_color='darkgray',$useAlpha=true) {
    1489         // This is complicated by the fact that we must also handle the case where
     1036        // Fill a rectangle with lines of two colors
     1037        if( $style===1 ) {
     1038            // Horizontal stripe
     1039            if( $yl < $yu ) {
     1040                $t = $yl; $yl=$yu; $yu=$t;
     1041            }
     1042            for( $y=$yu; $y <= $yl; ++$y) {
     1043                $this->SetColor($color1);
     1044                $this->Line($xl,$y,$xr,$y);
     1045                ++$y;
     1046                $this->SetColor($color2);
     1047                $this->Line($xl,$y,$xr,$y);
     1048            }
     1049        }
     1050        else {
     1051            if( $xl < $xl ) {
     1052                $t = $xl; $xl=$xr; $xr=$t;
     1053            }
     1054            for( $x=$xl; $x <= $xr; ++$x) {
     1055                $this->SetColor($color1);
     1056                $this->Line($x,$yu,$x,$yl);
     1057                ++$x;
     1058                $this->SetColor($color2);
     1059                $this->Line($x,$yu,$x,$yl);
     1060            }
     1061        }
     1062    }
     1063
     1064    function ShadowRectangle($xl,$yu,$xr,$yl,$fcolor=false,$shadow_width=3,$shadow_color=array(102,102,102)) {
     1065        // This is complicated by the fact that we must also handle the case where
    14901066        // the reactangle has no fill color
    1491         $xl = floor($xl);
    1492         $yu = floor($yu);
    1493         $xr = floor($xr);
    1494         $yl = floor($yl);
    1495         $this->PushColor($shadow_color);
    1496         $shadowAlpha=0;
    1497         $this->SetLineWeight(1);
    1498         $this->SetLineStyle('solid');
    1499         $basecolor = $this->rgb->Color($shadow_color);
    1500         $shadow_color = array($basecolor[0],$basecolor[1],$basecolor[2],);
    1501         for( $i=0; $i < $shadow_width; ++$i ) {
    1502             $this->SetColor($shadow_color,$shadowAlpha);
    1503             $this->Line($xr-$shadow_width+$i,   $yu+$shadow_width,
    1504                         $xr-$shadow_width+$i,   $yl-$shadow_width-1+$i);
    1505             $this->Line($xl+$shadow_width,   $yl-$shadow_width+$i,
    1506                         $xr-$shadow_width+$i,   $yl-$shadow_width+$i);
    1507             if( $useAlpha ) $shadowAlpha += 1.0/$shadow_width;
    1508         }
    1509 
    1510         $this->PopColor();
    1511         if( $fcolor==false ) {
    1512             $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1);
    1513         }
    1514         else {
    1515             $this->PushColor($fcolor);
    1516             $this->FilledRectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1);
    1517             $this->PopColor();
    1518             $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1);
    1519         }
     1067        $this->PushColor($shadow_color);
     1068        $this->FilledRectangle($xr-$shadow_width,$yu+$shadow_width,$xr,$yl-$shadow_width-1);
     1069        $this->FilledRectangle($xl+$shadow_width,$yl-$shadow_width,$xr,$yl);
     1070        //$this->FilledRectangle($xl+$shadow_width,$yu+$shadow_width,$xr,$yl);
     1071        $this->PopColor();
     1072        if( $fcolor==false )
     1073            $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1);
     1074        else {         
     1075            $this->PushColor($fcolor);
     1076            $this->FilledRectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1);
     1077            $this->PopColor();
     1078            $this->Rectangle($xl,$yu,$xr-$shadow_width-1,$yl-$shadow_width-1);
     1079        }
    15201080    }
    15211081
    15221082    function FilledRoundedRectangle($xt,$yt,$xr,$yl,$r=5) {
    1523         if( $r==0 ) {
    1524             $this->FilledRectangle($xt,$yt,$xr,$yl);
    1525             return;
    1526         }
    1527 
    1528         // To avoid overlapping fillings (which will look strange
    1529         // when alphablending is enabled) we have no choice but
    1530         // to fill the five distinct areas one by one.
    1531 
    1532         // Center square
    1533         $this->FilledRectangle($xt+$r,$yt+$r,$xr-$r,$yl-$r);
    1534         // Top band
    1535         $this->FilledRectangle($xt+$r,$yt,$xr-$r,$yt+$r);
    1536         // Bottom band
    1537         $this->FilledRectangle($xt+$r,$yl-$r,$xr-$r,$yl);
    1538         // Left band
    1539         $this->FilledRectangle($xt,$yt+$r,$xt+$r,$yl-$r);
    1540         // Right band
    1541         $this->FilledRectangle($xr-$r,$yt+$r,$xr,$yl-$r);
    1542 
    1543         // Topleft & Topright arc
    1544         $this->FilledArc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
    1545         $this->FilledArc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
    1546 
    1547         // Bottomleft & Bottom right arc
    1548         $this->FilledArc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
    1549         $this->FilledArc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
    1550 
    1551     }
    1552 
    1553     function RoundedRectangle($xt,$yt,$xr,$yl,$r=5) {
    1554 
    1555         if( $r==0 ) {
    1556             $this->Rectangle($xt,$yt,$xr,$yl);
    1557             return;
    1558         }
    1559 
    1560         // Top & Bottom line
    1561         $this->Line($xt+$r,$yt,$xr-$r,$yt);
    1562         $this->Line($xt+$r,$yl,$xr-$r,$yl);
    1563 
    1564         // Left & Right line
    1565         $this->Line($xt,$yt+$r,$xt,$yl-$r);
    1566         $this->Line($xr,$yt+$r,$xr,$yl-$r);
    1567 
    1568         // Topleft & Topright arc
    1569         $this->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
    1570         $this->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
    1571 
    1572         // Bottomleft & Bottomright arc
    1573         $this->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
    1574         $this->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
     1083        if( $r==0 ) {
     1084            $this->FilledRectangle($xt,$yt,$xr,$yl);
     1085            return;
     1086        }
     1087
     1088        // To avoid overlapping fillings (which will look strange
     1089        // when alphablending is enabled) we have no choice but
     1090        // to fill the five distinct areas one by one.
     1091       
     1092        // Center square
     1093        $this->FilledRectangle($xt+$r,$yt+$r,$xr-$r,$yl-$r);
     1094        // Top band
     1095        $this->FilledRectangle($xt+$r,$yt,$xr-$r,$yt+$r-1);
     1096        // Bottom band
     1097        $this->FilledRectangle($xt+$r,$yl-$r+1,$xr-$r,$yl);
     1098        // Left band
     1099        $this->FilledRectangle($xt,$yt+$r+1,$xt+$r-1,$yl-$r);
     1100        // Right band
     1101        $this->FilledRectangle($xr-$r+1,$yt+$r,$xr,$yl-$r);
     1102
     1103        // Topleft & Topright arc
     1104        $this->FilledArc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
     1105        $this->FilledArc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
     1106
     1107        // Bottomleft & Bottom right arc
     1108        $this->FilledArc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
     1109        $this->FilledArc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
     1110
     1111    }
     1112
     1113    function RoundedRectangle($xt,$yt,$xr,$yl,$r=5) {   
     1114
     1115        if( $r==0 ) {
     1116            $this->Rectangle($xt,$yt,$xr,$yl);
     1117            return;
     1118        }
     1119
     1120        // Top & Bottom line
     1121        $this->Line($xt+$r,$yt,$xr-$r,$yt);
     1122        $this->Line($xt+$r,$yl,$xr-$r,$yl);
     1123
     1124        // Left & Right line
     1125        $this->Line($xt,$yt+$r,$xt,$yl-$r);
     1126        $this->Line($xr,$yt+$r,$xr,$yl-$r);
     1127
     1128        // Topleft & Topright arc
     1129        $this->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
     1130        $this->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
     1131
     1132        // Bottomleft & Bottomright arc
     1133        $this->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
     1134        $this->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
    15751135    }
    15761136
    15771137    function FilledBevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='darkgray@0.4') {
    1578         $this->FilledRectangle($x1,$y1,$x2,$y2);
    1579         $this->Bevel($x1,$y1,$x2,$y2,$depth,$color1,$color2);
     1138        $this->FilledRectangle($x1,$y1,$x2,$y2);
     1139        $this->Bevel($x1,$y1,$x2,$y2,$depth,$color1,$color2);
    15801140    }
    15811141
    15821142    function Bevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='black@0.5') {
    1583         $this->PushColor($color1);
    1584         for( $i=0; $i < $depth; ++$i ) {
    1585             $this->Line($x1+$i,$y1+$i,$x1+$i,$y2-$i);
    1586             $this->Line($x1+$i,$y1+$i,$x2-$i,$y1+$i);
    1587         }
    1588         $this->PopColor();
    1589 
    1590         $this->PushColor($color2);
    1591         for( $i=0; $i < $depth; ++$i ) {
    1592             $this->Line($x1+$i,$y2-$i,$x2-$i,$y2-$i);
    1593             $this->Line($x2-$i,$y1+$i,$x2-$i,$y2-$i-1);
    1594         }
    1595         $this->PopColor();
     1143        $this->PushColor($color1);
     1144        for( $i=0; $i < $depth; ++$i ) {
     1145            $this->Line($x1+$i,$y1+$i,$x1+$i,$y2-$i);
     1146            $this->Line($x1+$i,$y1+$i,$x2-$i,$y1+$i);
     1147        }
     1148        $this->PopColor();
     1149       
     1150        $this->PushColor($color2);
     1151        for( $i=0; $i < $depth; ++$i ) {
     1152            $this->Line($x1+$i,$y2-$i,$x2-$i,$y2-$i);
     1153            $this->Line($x2-$i,$y1+$i,$x2-$i,$y2-$i-1);
     1154        }
     1155        $this->PopColor();
    15961156    }
    15971157
    15981158    function StyleLineTo($x,$y) {
    1599         $this->StyleLine($this->lastx,$this->lasty,$x,$y);
    1600         $this->lastx=$x;
    1601         $this->lasty=$y;
    1602     }
    1603 
     1159        $this->StyleLine($this->lastx,$this->lasty,$x,$y);
     1160        $this->lastx=$x;
     1161        $this->lasty=$y;
     1162    }
     1163       
    16041164    function LineTo($x,$y) {
    1605         $this->Line($this->lastx,$this->lasty,$x,$y);
    1606         $this->lastx=$x;
    1607         $this->lasty=$y;
    1608     }
    1609 
     1165        $this->Line($this->lastx,$this->lasty,$x,$y);
     1166        $this->lastx=$x;
     1167        $this->lasty=$y;
     1168    }
     1169       
    16101170    function Point($x,$y) {
    1611         imagesetpixel($this->img,round($x),round($y),$this->current_color);
    1612     }
    1613 
     1171        imagesetpixel($this->img,round($x),round($y),$this->current_color);
     1172    }
     1173       
    16141174    function Fill($x,$y) {
    1615         imagefill($this->img,round($x),round($y),$this->current_color);
     1175        imagefill($this->img,round($x),round($y),$this->current_color);
    16161176    }
    16171177
    16181178    function FillToBorder($x,$y,$aBordColor) {
    1619         $bc = $this->rgb->allocate($aBordColor);
    1620         if( $bc == -1 ) {
    1621             JpGraphError::RaiseL(25106);//('Image::FillToBorder : Can not allocate more colors');
    1622         }
    1623         imagefilltoborder($this->img,round($x),round($y),$bc,$this->current_color);
     1179        $bc = $this->rgb->allocate($aBordColor);
     1180        if( $bc == -1 ) {
     1181            JpGraphError::RaiseL(25106);//('Image::FillToBorder : Can not allocate more colors');
     1182        }
     1183        imagefilltoborder($this->img,round($x),round($y),$bc,$this->current_color);
    16241184    }
    16251185
    16261186    function SetExpired($aFlg=true) {
    1627         $this->expired = $aFlg;
    1628     }
    1629 
     1187        $this->expired = $aFlg;
     1188    }
     1189       
    16301190    // Generate image header
    16311191    function Headers() {
    1632 
    1633         // In case we are running from the command line with the client version of
    1634         // PHP we can't send any headers.
    1635         $sapi = php_sapi_name();
    1636         if( $sapi == 'cli' ) return;
    1637 
    1638         // These parameters are set by headers_sent() but they might cause
    1639         // an undefined variable error unless they are initilized
    1640         $file='';
    1641         $lineno='';
    1642         if( headers_sent($file,$lineno) ) {
    1643             $file=basename($file);
    1644             $t = new ErrMsgText();
    1645             $msg = $t->Get(10,$file,$lineno);
    1646             die($msg);
    1647         }
    1648 
    1649         if ($this->expired) {
    1650             header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
    1651             header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
    1652             header("Cache-Control: no-cache, must-revalidate");
    1653             header("Pragma: no-cache");
    1654         }
    1655         header("Content-type: image/$this->img_format");
     1192       
     1193        // In case we are running from the command line with the client version of
     1194        // PHP we can't send any headers.
     1195        $sapi = php_sapi_name();
     1196        if( $sapi == 'cli' )
     1197            return;
     1198
     1199        // These parameters are set by headers_sent() but they might cause
     1200        // an undefined variable error unless they are initilized
     1201        $file='';
     1202        $lineno='';
     1203        if( headers_sent($file,$lineno) ) {
     1204            $file=basename($file);         
     1205            $t = new ErrMsgText();
     1206            $msg = $t->Get(10,$file,$lineno);
     1207            die($msg);
     1208        }       
     1209       
     1210        if ($this->expired) {
     1211            header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
     1212            header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
     1213            header("Cache-Control: no-cache, must-revalidate");
     1214            header("Pragma: no-cache");
     1215        }
     1216        header("Content-type: image/$this->img_format");
    16561217    }
    16571218
    16581219    // Adjust image quality for formats that allow this
    16591220    function SetQuality($q) {
    1660         $this->quality = $q;
    1661     }
    1662 
     1221        $this->quality = $q;
     1222    }
     1223       
    16631224    // Stream image to browser or to file
    1664     function Stream($aFile=NULL) {
    1665         $this->DoSupersampling();
    1666 
    1667         $func="image".$this->img_format;
    1668         if( $this->img_format=="jpeg" && $this->quality != null ) {
    1669             $res = @$func($this->img,$aFile,$this->quality);
    1670                        
    1671                         if(!$res){
    1672                                 if($aFile != NULL){     
    1673                     JpGraphError::RaiseL(25107,$aFile);//("Can't write to file '$aFile'. Check that the process running PHP has enough permission.");
    1674                                 }else{
    1675                     JpGraphError::RaiseL(25108);//("Can't stream image. This is most likely due to a faulty PHP/GD setup. Try to recompile PHP and use the built-in GD library that comes with PHP.");
    1676                                 }
     1225    function Stream($aFile="") {
     1226        $func="image".$this->img_format;
     1227        if( $this->img_format=="jpeg" && $this->quality != null ) {
     1228            $res = @$func($this->img,$aFile,$this->quality);
     1229        }
     1230        else {
     1231            if( $aFile != "" ) {
     1232                $res = @$func($this->img,$aFile);
     1233                if( !$res )
     1234                    JpGraphError::RaiseL(25107,$aFile);//("Can't write to file '$aFile'. Check that the process running PHP has enough permission.");
     1235            }
     1236            else {
     1237                $res = @$func($this->img);
     1238                if( !$res )
     1239                    JpGraphError::RaiseL(25108);//("Can't stream image. This is most likely due to a faulty PHP/GD setup. Try to recompile PHP and use the built-in GD library that comes with PHP.");
    16771240               
    1678                         }
    1679                 }
    1680         else {
    1681             if( $aFile != NULL ) {
    1682                 $res = @$func($this->img,$aFile);
    1683                 if( !$res ) {
    1684                     JpGraphError::RaiseL(25107,$aFile);//("Can't write to file '$aFile'. Check that the process running PHP has enough permission.");
    1685                 }
    1686             }
    1687             else {
    1688                 $res = @$func($this->img);
    1689                 if( !$res ) {
    1690                     JpGraphError::RaiseL(25108);//("Can't stream image. This is most likely due to a faulty PHP/GD setup. Try to recompile PHP and use the built-in GD library that comes with PHP.");
    1691                 }
    1692 
    1693             }
    1694         }
    1695     }
    1696 
    1697     // Do SuperSampling using $scale
    1698     function DoSupersampling() {
    1699         if (SUPERSAMPLING_SCALE <= 1) {
    1700             return $this->img;
    1701         }
    1702 
    1703         $dst_img = @imagecreatetruecolor($this->original_width, $this->original_height);
    1704         imagecopyresampled($dst_img, $this->img, 0, 0, 0, 0, $this->original_width, $this->original_height, $this->width, $this->height);
    1705         $this->Destroy();
    1706         return $this->img = $dst_img;
    1707     }
    1708 
    1709     // Clear resources used by image (this is normally not used since all resources are/should be
    1710     // returned when the script terminates
     1241            }
     1242        }
     1243    }
     1244               
     1245    // Clear resource tide up by image
    17111246    function Destroy() {
    1712         imagedestroy($this->img);
    1713     }
    1714 
     1247        imagedestroy($this->img);
     1248    }
     1249       
    17151250    // Specify image format. Note depending on your installation
    17161251    // of PHP not all formats may be supported.
    1717     function SetImgFormat($aFormat,$aQuality=75) {
    1718         $this->quality = $aQuality;
    1719         $aFormat = strtolower($aFormat);
    1720         $tst = true;
    1721         $supported = imagetypes();
    1722         if( $aFormat=="auto" ) {
    1723             if( $supported & IMG_PNG )      $this->img_format="png";
    1724             elseif( $supported & IMG_JPG )  $this->img_format="jpeg";
    1725             elseif( $supported & IMG_GIF )  $this->img_format="gif";
    1726             elseif( $supported & IMG_WBMP ) $this->img_format="wbmp";
    1727             elseif( $supported & IMG_XPM )  $this->img_format="xpm";
    1728             else {
    1729                 JpGraphError::RaiseL(25109);//("Your PHP (and GD-lib) installation does not appear to support any known graphic formats. You need to first make sure GD is compiled as a module to PHP. If you also want to use JPEG images you must get the JPEG library. Please see the PHP docs for details.");
    1730             }
    1731             return true;
    1732         }
    1733         else {
    1734             if( $aFormat=="jpeg" || $aFormat=="png" || $aFormat=="gif" ) {
    1735                 if( $aFormat=="jpeg" && !($supported & IMG_JPG) )       $tst=false;
    1736                 elseif( $aFormat=="png" && !($supported & IMG_PNG) )    $tst=false;
    1737                 elseif( $aFormat=="gif" && !($supported & IMG_GIF) )    $tst=false;
    1738                 elseif( $aFormat=="wbmp" && !($supported & IMG_WBMP) )  $tst=false;
    1739                 elseif( $aFormat=="xpm" && !($supported & IMG_XPM) )    $tst=false;
    1740                 else {
    1741                     $this->img_format=$aFormat;
    1742                     return true;
    1743                 }
    1744             }
    1745             else {
    1746                 $tst=false;
    1747             }
    1748             if( !$tst ) {
    1749                 JpGraphError::RaiseL(25110,$aFormat);//(" Your PHP installation does not support the chosen graphic format: $aFormat");
    1750             }
    1751         }
    1752     }
    1753 
    1754     /**
    1755     * Draw Line
    1756     */
    1757     function DrawLine($im, $x1, $y1, $x2, $y2, $weight, $color) {
    1758         if ($weight == 1) {
    1759             return imageline($im,$x1,$y1,$x2,$y2,$color);
    1760         }
    1761 
    1762         $angle=(atan2(($y1 - $y2), ($x2 - $x1)));
    1763 
    1764         $dist_x = $weight * (sin($angle)) / 2;
    1765         $dist_y = $weight * (cos($angle)) / 2;
    1766        
    1767         $p1x=ceil(($x1 + $dist_x));
    1768         $p1y=ceil(($y1 + $dist_y));
    1769         $p2x=ceil(($x2 + $dist_x));
    1770         $p2y=ceil(($y2 + $dist_y));
    1771         $p3x=ceil(($x2 - $dist_x));
    1772         $p3y=ceil(($y2 - $dist_y));
    1773         $p4x=ceil(($x1 - $dist_x));
    1774         $p4y=ceil(($y1 - $dist_y));
    1775 
    1776         $array=array($p1x,$p1y,$p2x,$p2y,$p3x,$p3y,$p4x,$p4y);
    1777         imagefilledpolygon ( $im, $array, (count($array)/2), $color );
    1778 
    1779         // for antialias
    1780         imageline($im, $p1x, $p1y, $p2x, $p2y, $color);
    1781         imageline($im, $p3x, $p3y, $p4x, $p4y, $color);
    1782         return;
    1783 
    1784 
    1785 
    1786           return imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color);
    1787       $weight = 8;
    1788         if ($weight <= 1) {
    1789           return imageline($this->img,$x1,$y1,$x2,$y2,$this->current_color);
    1790         }
    1791 
    1792         $pts = array();
    1793 
    1794         $weight /= 2;
    1795 
    1796         if ($y2 - $y1 == 0) {
    1797             // x line
    1798             $pts = array();
    1799             $pts[] = $x1; $pts[] = $y1 - $weight;
    1800             $pts[] = $x1; $pts[] = $y1 + $weight;
    1801             $pts[] = $x2; $pts[] = $y2 + $weight;
    1802             $pts[] = $x2; $pts[] = $y2 - $weight;
    1803 
    1804         } elseif ($x2 - $x1 == 0) {
    1805             // y line
    1806             $pts = array();
    1807             $pts[] = $x1 - $weight; $pts[] = $y1;
    1808             $pts[] = $x1 + $weight; $pts[] = $y1;
    1809             $pts[] = $x2 + $weight; $pts[] = $y2;
    1810             $pts[] = $x2 - $weight; $pts[] = $y2;
    1811 
    1812         } else {
    1813            
    1814             var_dump($x1, $x2, $y1, $y2);
    1815             $length = sqrt(pow($x2 - $x1, 2) + pow($y2 - $y1, 2));
    1816             var_dump($length);exit;
    1817             exit;
    1818  
    1819 /*
    1820             $lean = ($y2 - $y1) / ($x2 - $x1);
    1821             $lean2 = -1 / $lean;
    1822             $sin = $lean / ($y2 - $y1);
    1823             $cos = $lean / ($x2 - $x1);
    1824 
    1825             $pts[] = $x1 + (-$weight * $sin); $pts[] = $y1 + (-$weight * $cos);
    1826             $pts[] = $x1 + (+$weight * $sin); $pts[] = $y1 + (+$weight * $cos);
    1827             $pts[] = $x2 + (+$weight * $sin); $pts[] = $y2 + (+$weight * $cos);
    1828             $pts[] = $x2 + (-$weight * $sin); $pts[] = $y2 + (-$weight * $cos);
    1829 */
    1830         }
    1831 
    1832 //print_r($pts);exit;
    1833         if (count($pts)/2 < 3) {
    1834             return;
    1835         }
    1836 
    1837         imagesetthickness($im, 1);
    1838         imagefilledpolygon($im, $pts,count($pts)/2, $color);
    1839 
    1840 
    1841         $weight *= 2;
    1842 
    1843 //        $this->DrawImageSmoothArc($im, $x1, $y1, $weight, $weight, 0, 360, $color);
    1844 //        $this->DrawImageSmoothArc($im, $x2, $y2, $weight, $weight, 0, 360, $color);
    1845     }
    1846 
    1847 
    1848     function DrawImageSmoothArc($im, $xc, $yc, $w, $h, $s, $e, $color, $style = null) {
    1849         $tmp = $s;
    1850         $s = (360 - $e) / 180 * M_PI;
    1851         $e = (360 - $tmp) / 180 * M_PI;
    1852         return imageSmoothArc($im, round($xc), round($yc), round($w), round($h), $this->CreateColorForImageSmoothArc($color), $s, $e);
    1853     }
    1854 
    1855     function CreateColorForImageSmoothArc($color) {
    1856         $alpha = $color >> 24 & 0xFF;
    1857         $red   = $color >> 16 & 0xFF;
    1858         $green = $color >> 8 & 0xFF;
    1859         $blue  = $color & 0xFF;
    1860 
    1861 //var_dump($alpha, $red, $green, $blue);exit;
    1862 
    1863         return array($red, $green, $blue, $alpha);
    1864     }
    1865 
    1866     function imageSmoothCircle( &$img, $cx, $cy, $cr, $color ) {
    1867         $ir = $cr;
    1868         $ix = 0;
    1869         $iy = $ir;
    1870         $ig = 2 * $ir - 3;
    1871         $idgr = -6;
    1872         $idgd = 4 * $ir - 10;
    1873         $fill = imageColorExactAlpha( $img, $color[ 'R' ], $color[ 'G' ], $color[ 'B' ], 0 );
    1874         imageLine( $img, $cx + $cr - 1, $cy, $cx, $cy, $fill );
    1875         imageLine( $img, $cx - $cr + 1, $cy, $cx - 1, $cy, $fill );
    1876         imageLine( $img, $cx, $cy + $cr - 1, $cx, $cy + 1, $fill );
    1877         imageLine( $img, $cx, $cy - $cr + 1, $cx, $cy - 1, $fill );
    1878         $draw = imageColorExactAlpha( $img, $color[ 'R' ], $color[ 'G' ], $color[ 'B' ], 42 );
    1879         imageSetPixel( $img, $cx + $cr, $cy, $draw );
    1880         imageSetPixel( $img, $cx - $cr, $cy, $draw );
    1881         imageSetPixel( $img, $cx, $cy + $cr, $draw );
    1882         imageSetPixel( $img, $cx, $cy - $cr, $draw );
    1883         while ( $ix <= $iy - 2 ) {
    1884             if ( $ig < 0 ) {
    1885                 $ig += $idgd;
    1886                 $idgd -= 8;
    1887                 $iy--;
    1888             } else {
    1889                 $ig += $idgr;
    1890                 $idgd -= 4;
    1891             }
    1892             $idgr -= 4;
    1893             $ix++;
    1894             imageLine( $img, $cx + $ix, $cy + $iy - 1, $cx + $ix, $cy + $ix, $fill );
    1895             imageLine( $img, $cx + $ix, $cy - $iy + 1, $cx + $ix, $cy - $ix, $fill );
    1896             imageLine( $img, $cx - $ix, $cy + $iy - 1, $cx - $ix, $cy + $ix, $fill );
    1897             imageLine( $img, $cx - $ix, $cy - $iy + 1, $cx - $ix, $cy - $ix, $fill );
    1898             imageLine( $img, $cx + $iy - 1, $cy + $ix, $cx + $ix, $cy + $ix, $fill );
    1899             imageLine( $img, $cx + $iy - 1, $cy - $ix, $cx + $ix, $cy - $ix, $fill );
    1900             imageLine( $img, $cx - $iy + 1, $cy + $ix, $cx - $ix, $cy + $ix, $fill );
    1901             imageLine( $img, $cx - $iy + 1, $cy - $ix, $cx - $ix, $cy - $ix, $fill );
    1902             $filled = 0;
    1903             for ( $xx = $ix - 0.45; $xx < $ix + 0.5; $xx += 0.2 ) {
    1904                 for ( $yy = $iy - 0.45; $yy < $iy + 0.5; $yy += 0.2 ) {
    1905                     if ( sqrt( pow( $xx, 2 ) + pow( $yy, 2 ) ) < $cr ) $filled += 4;
    1906                 }
    1907             }
    1908             $draw = imageColorExactAlpha( $img, $color[ 'R' ], $color[ 'G' ], $color[ 'B' ], ( 100 - $filled ) );
    1909             imageSetPixel( $img, $cx + $ix, $cy + $iy, $draw );
    1910             imageSetPixel( $img, $cx + $ix, $cy - $iy, $draw );
    1911             imageSetPixel( $img, $cx - $ix, $cy + $iy, $draw );
    1912             imageSetPixel( $img, $cx - $ix, $cy - $iy, $draw );
    1913             imageSetPixel( $img, $cx + $iy, $cy + $ix, $draw );
    1914             imageSetPixel( $img, $cx + $iy, $cy - $ix, $draw );
    1915             imageSetPixel( $img, $cx - $iy, $cy + $ix, $draw );
    1916             imageSetPixel( $img, $cx - $iy, $cy - $ix, $draw );
    1917         }
    1918     }
    1919 
    1920     function __get($name) {
    1921 
    1922         if (strpos($name, 'raw_') !== false) {
    1923             // if $name == 'raw_left_margin' , return $this->_left_margin;
    1924             $variable_name = '_' . str_replace('raw_', '', $name);
    1925             return $this->$variable_name;
    1926         }
    1927 
    1928         $variable_name = '_' . $name;
    1929 
    1930         if (isset($this->$variable_name)) {
    1931             return $this->$variable_name * SUPERSAMPLING_SCALE;
    1932         } else {
    1933             JpGraphError::RaiseL('25132', $name);
    1934         }
    1935     }
    1936 
    1937     function __set($name, $value) {
    1938         $this->{'_'.$name} = $value;
    1939     }
    1940 
     1252    function SetImgFormat($aFormat,$aQuality=75) {             
     1253        $this->quality = $aQuality;
     1254        $aFormat = strtolower($aFormat);
     1255        $tst = true;
     1256        $supported = imagetypes();
     1257        if( $aFormat=="auto" ) {
     1258            if( $supported & IMG_PNG )
     1259                $this->img_format="png";
     1260            elseif( $supported & IMG_JPG )
     1261                $this->img_format="jpeg";
     1262            elseif( $supported & IMG_GIF )
     1263                $this->img_format="gif";
     1264            elseif( $supported & IMG_WBMP )
     1265                $this->img_format="wbmp";
     1266            elseif( $supported & IMG_XPM )
     1267                $this->img_format="xpm";
     1268            else
     1269                JpGraphError::RaiseL(25109);//("Your PHP (and GD-lib) installation does not appear to support any known graphic formats. You need to first make sure GD is compiled as a module to PHP. If you also want to use JPEG images you must get the JPEG library. Please see the PHP docs for details.");
     1270                               
     1271            return true;
     1272        }
     1273        else {
     1274            if( $aFormat=="jpeg" || $aFormat=="png" || $aFormat=="gif" ) {
     1275                if( $aFormat=="jpeg" && !($supported & IMG_JPG) )
     1276                    $tst=false;
     1277                elseif( $aFormat=="png" && !($supported & IMG_PNG) )
     1278                    $tst=false;
     1279                elseif( $aFormat=="gif" && !($supported & IMG_GIF) )   
     1280                    $tst=false;
     1281                elseif( $aFormat=="wbmp" && !($supported & IMG_WBMP) ) 
     1282                    $tst=false;
     1283                elseif( $aFormat=="xpm" && !($supported & IMG_XPM) )   
     1284                    $tst=false;
     1285                else {
     1286                    $this->img_format=$aFormat;
     1287                    return true;
     1288                }
     1289            }
     1290            else
     1291                $tst=false;
     1292            if( !$tst )
     1293                JpGraphError::RaiseL(25110,$aFormat);//(" Your PHP installation does not support the chosen graphic format: $aFormat");
     1294        }
     1295    }   
    19411296} // CLASS
    19421297
     
    19481303class RotImage extends Image {
    19491304    public $a=0;
    1950     public $dx=0,$dy=0,$transx=0,$transy=0;
     1305    public $dx=0,$dy=0,$transx=0,$transy=0; 
    19511306    private $m=array();
    1952 
    1953     function __construct($aWidth,$aHeight,$a=0,$aFormat=DEFAULT_GFORMAT,$aSetAutoMargin=true) {
    1954         parent::__construct($aWidth,$aHeight,$aFormat,$aSetAutoMargin);
    1955         $this->dx=$this->width/2;
    1956         $this->dy=$this->height/2;
    1957         $this->SetAngle($a);
    1958     }
    1959 
     1307       
     1308    function RotImage($aWidth,$aHeight,$a=0,$aFormat=DEFAULT_GFORMAT,$aSetAutoMargin=true) {
     1309        $this->Image($aWidth,$aHeight,$aFormat,$aSetAutoMargin);
     1310        $this->dx=$this->left_margin+$this->plotwidth/2;
     1311        $this->dy=$this->top_margin+$this->plotheight/2;
     1312        $this->SetAngle($a);   
     1313    }
     1314       
    19601315    function SetCenter($dx,$dy) {
    1961         $old_dx = $this->dx;
    1962         $old_dy = $this->dy;
    1963         $this->dx=$dx;
    1964         $this->dy=$dy;
    1965         $this->SetAngle($this->a);
    1966         return array($old_dx,$old_dy);
    1967     }
    1968 
     1316        $old_dx = $this->dx;
     1317        $old_dy = $this->dy;
     1318        $this->dx=$dx;
     1319        $this->dy=$dy;
     1320        $this->SetAngle($this->a);
     1321        return array($old_dx,$old_dy);
     1322    }
     1323       
    19691324    function SetTranslation($dx,$dy) {
    1970         $old = array($this->transx,$this->transy);
    1971         $this->transx = $dx;
    1972         $this->transy = $dy;
    1973         return $old;
     1325        $old = array($this->transx,$this->transy);
     1326        $this->transx = $dx;
     1327        $this->transy = $dy;
     1328        return $old;
    19741329    }
    19751330
    19761331    function UpdateRotMatrice()  {
    1977         $a = $this->a;
    1978         $a *= M_PI/180;
    1979         $sa=sin($a); $ca=cos($a);
    1980         // Create the rotation matrix
    1981         $this->m[0][0] = $ca;
    1982         $this->m[0][1] = -$sa;
    1983         $this->m[0][2] = $this->dx*(1-$ca) + $sa*$this->dy ;
    1984         $this->m[1][0] = $sa;
    1985         $this->m[1][1] = $ca;
    1986         $this->m[1][2] = $this->dy*(1-$ca) - $sa*$this->dx ;
     1332        $a = $this->a;
     1333        $a *= M_PI/180;
     1334        $sa=sin($a); $ca=cos($a);               
     1335        // Create the rotation matrix
     1336        $this->m[0][0] = $ca;
     1337        $this->m[0][1] = -$sa;
     1338        $this->m[0][2] = $this->dx*(1-$ca) + $sa*$this->dy ;
     1339        $this->m[1][0] = $sa;
     1340        $this->m[1][1] = $ca;
     1341        $this->m[1][2] = $this->dy*(1-$ca) - $sa*$this->dx ;
    19871342    }
    19881343
    19891344    function SetAngle($a) {
    1990         $tmp = $this->a;
    1991         $this->a = $a;
    1992         $this->UpdateRotMatrice();
    1993         return $tmp;
     1345        $tmp = $this->a;
     1346        $this->a = $a;
     1347        $this->UpdateRotMatrice();
     1348        return $tmp;
    19941349    }
    19951350
    19961351    function Circle($xc,$yc,$r) {
    1997         list($xc,$yc) = $this->Rotate($xc,$yc);
    1998         parent::Circle($xc,$yc,$r);
     1352        list($xc,$yc) = $this->Rotate($xc,$yc);
     1353        parent::Circle($xc,$yc,$r);
    19991354    }
    20001355
    20011356    function FilledCircle($xc,$yc,$r) {
    2002         list($xc,$yc) = $this->Rotate($xc,$yc);
    2003         parent::FilledCircle($xc,$yc,$r);
    2004     }
    2005 
    2006 
     1357        list($xc,$yc) = $this->Rotate($xc,$yc);
     1358        parent::FilledCircle($xc,$yc,$r);
     1359    }
     1360
     1361       
    20071362    function Arc($xc,$yc,$w,$h,$s,$e) {
    2008         list($xc,$yc) = $this->Rotate($xc,$yc);
    2009         $s += $this->a;
    2010         $e += $this->a;
    2011         parent::Arc($xc,$yc,$w,$h,$s,$e);
     1363        list($xc,$yc) = $this->Rotate($xc,$yc);
     1364        $s += $this->a;
     1365        $e += $this->a;
     1366        parent::Arc($xc,$yc,$w,$h,$s,$e);
    20121367    }
    20131368
    20141369    function FilledArc($xc,$yc,$w,$h,$s,$e,$style='') {
    2015         list($xc,$yc) = $this->Rotate($xc,$yc);
    2016         $s += $this->a;
    2017         $e += $this->a;
    2018         parent::FilledArc($xc,$yc,$w,$h,$s,$e);
     1370        list($xc,$yc) = $this->Rotate($xc,$yc);
     1371        $s += $this->a;
     1372        $e += $this->a;
     1373        parent::FilledArc($xc,$yc,$w,$h,$s,$e);
    20191374    }
    20201375
    20211376    function SetMargin($lm,$rm,$tm,$bm) {
    2022         parent::SetMargin($lm,$rm,$tm,$bm);
    2023         $this->UpdateRotMatrice();
    2024     }
    2025 
     1377        parent::SetMargin($lm,$rm,$tm,$bm);
     1378        $this->dx=$this->left_margin+$this->plotwidth/2;
     1379        $this->dy=$this->top_margin+$this->plotheight/2;
     1380        $this->UpdateRotMatrice();
     1381    }
     1382       
    20261383    function Rotate($x,$y) {
    2027         // Optimization. Ignore rotation if Angle==0 || Angle==360
    2028         if( $this->a == 0 || $this->a == 360 ) {
    2029             return array($x + $this->transx, $y + $this->transy );
    2030         }
    2031         else {
    2032             $x1=round($this->m[0][0]*$x + $this->m[0][1]*$y,1) + $this->m[0][2] + $this->transx;
    2033             $y1=round($this->m[1][0]*$x + $this->m[1][1]*$y,1) + $this->m[1][2] + $this->transy;
    2034             return array($x1,$y1);
    2035         }
    2036     }
    2037 
     1384        // Optimization. Ignore rotation if Angle==0 || Angle==360
     1385        if( $this->a == 0 || $this->a == 360 ) {
     1386            return array($x + $this->transx, $y + $this->transy );
     1387        }
     1388        else {
     1389            $x1=round($this->m[0][0]*$x + $this->m[0][1]*$y,1) + $this->m[0][2] + $this->transx;
     1390            $y1=round($this->m[1][0]*$x + $this->m[1][1]*$y,1) + $this->m[1][2] + $this->transy;
     1391            return array($x1,$y1);
     1392        }
     1393    }
     1394       
    20381395    function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) {
    2039         list($toX,$toY) = $this->Rotate($toX,$toY);
    2040         parent::CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight,$aMix);
     1396        list($toX,$toY) = $this->Rotate($toX,$toY);
     1397        parent::CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight,$aMix);
    20411398
    20421399    }
    20431400
    20441401    function ArrRotate($pnts) {
    2045         $n = count($pnts)-1;
    2046         for($i=0; $i < $n; $i+=2) {
    2047             list ($x,$y) = $this->Rotate($pnts[$i],$pnts[$i+1]);
    2048             $pnts[$i] = $x; $pnts[$i+1] = $y;
    2049         }
    2050         return $pnts;
     1402        $n = count($pnts)-1;
     1403        for($i=0; $i < $n; $i+=2) {
     1404            list ($x,$y) = $this->Rotate($pnts[$i],$pnts[$i+1]);
     1405            $pnts[$i] = $x; $pnts[$i+1] = $y;
     1406        }
     1407        return $pnts;
    20511408    }
    20521409
    20531410    function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) {
    2054         list($x1,$y1) = $this->Rotate($x1,$y1);
    2055         list($x2,$y2) = $this->Rotate($x2,$y2);
    2056         parent::DashedLine($x1,$y1,$x2,$y2,$dash_length,$dash_space);
    2057     }
    2058 
     1411        list($x1,$y1) = $this->Rotate($x1,$y1);
     1412        list($x2,$y2) = $this->Rotate($x2,$y2);
     1413        parent::DashedLine($x1,$y1,$x2,$y2,$dash_length,$dash_space);
     1414    }
     1415       
    20591416    function Line($x1,$y1,$x2,$y2) {
    2060         list($x1,$y1) = $this->Rotate($x1,$y1);
    2061         list($x2,$y2) = $this->Rotate($x2,$y2);
    2062         parent::Line($x1,$y1,$x2,$y2);
     1417        list($x1,$y1) = $this->Rotate($x1,$y1);
     1418        list($x2,$y2) = $this->Rotate($x2,$y2);
     1419        parent::Line($x1,$y1,$x2,$y2);
    20631420    }
    20641421
    20651422    function Rectangle($x1,$y1,$x2,$y2) {
    2066         // Rectangle uses Line() so it will be rotated through that call
    2067         parent::Rectangle($x1,$y1,$x2,$y2);
    2068     }
    2069 
     1423        // Rectangle uses Line() so it will be rotated through that call
     1424        parent::Rectangle($x1,$y1,$x2,$y2);
     1425    }
     1426       
    20701427    function FilledRectangle($x1,$y1,$x2,$y2) {
    2071         if( $y1==$y2 || $x1==$x2 )
    2072         $this->Line($x1,$y1,$x2,$y2);
    2073         else
    2074         $this->FilledPolygon(array($x1,$y1,$x2,$y1,$x2,$y2,$x1,$y2));
    2075     }
    2076 
     1428        if( $y1==$y2 || $x1==$x2 )
     1429            $this->Line($x1,$y1,$x2,$y2);
     1430        else
     1431            $this->FilledPolygon(array($x1,$y1,$x2,$y1,$x2,$y2,$x1,$y2));
     1432    }
     1433       
    20771434    function Polygon($pnts,$closed=FALSE,$fast=FALSE) {
    2078         // Polygon uses Line() so it will be rotated through that call unless
    2079         // fast drawing routines are used in which case a rotate is needed
    2080         if( $fast ) {
    2081             parent::Polygon($this->ArrRotate($pnts));
    2082         }
    2083         else {
    2084             parent::Polygon($pnts,$closed,$fast);
    2085         }
    2086     }
    2087 
     1435        // Polygon uses Line() so it will be rotated through that call unless
     1436        // fast drawing routines are used in which case a rotate is needed
     1437        if( $fast ) {
     1438            parent::Polygon($this->ArrRotate($pnts));
     1439        }
     1440        else
     1441            parent::Polygon($pnts,$closed,$fast);
     1442    }
     1443       
    20881444    function FilledPolygon($pnts) {
    2089         parent::FilledPolygon($this->ArrRotate($pnts));
    2090     }
    2091 
     1445        parent::FilledPolygon($this->ArrRotate($pnts));
     1446    }
     1447       
    20921448    function Point($x,$y) {
    2093         list($xp,$yp) = $this->Rotate($x,$y);
    2094         parent::Point($xp,$yp);
    2095     }
    2096 
     1449        list($xp,$yp) = $this->Rotate($x,$y);
     1450        parent::Point($xp,$yp);
     1451    }
     1452       
    20971453    function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) {
    2098         list($xp,$yp) = $this->Rotate($x,$y);
    2099         return parent::StrokeText($xp,$yp,$txt,$dir,$paragraph_align,$debug);
     1454        list($xp,$yp) = $this->Rotate($x,$y);
     1455        return parent::StrokeText($xp,$yp,$txt,$dir,$paragraph_align,$debug);
    21001456    }
    21011457}
    21021458
    2103 //=======================================================================
     1459//===================================================
    21041460// CLASS ImgStreamCache
    2105 // Description: Handle caching of graphs to files. All image output goes
    2106 //              through this class
    2107 //=======================================================================
     1461// Description: Handle caching of graphs to files
     1462//===================================================
    21081463class ImgStreamCache {
    2109     private $cache_dir, $timeout=0;  // Infinite timeout
     1464    private $cache_dir, $img=null, $timeout=0;  // Infinite timeout
    21101465    //---------------
    21111466    // CONSTRUCTOR
    2112     function __construct($aCacheDir=CACHE_DIR) {
    2113         $this->cache_dir = $aCacheDir;
    2114     }
    2115 
    2116     //---------------
    2117     // PUBLIC METHODS
     1467    function ImgStreamCache($aImg, $aCacheDir=CACHE_DIR) {
     1468        $this->img = $aImg;
     1469        $this->cache_dir = $aCacheDir;
     1470    }
     1471
     1472//---------------
     1473// PUBLIC METHODS       
    21181474
    21191475    // Specify a timeout (in minutes) for the file. If the file is older then the
     
    21221478    // timeout is set to -1 this is the same as infinite small timeout
    21231479    function SetTimeout($aTimeout) {
    2124         $this->timeout=$aTimeout;
    2125     }
    2126 
     1480        $this->timeout=$aTimeout;       
     1481    }
     1482       
    21271483    // Output image to browser and also write it to the cache
    21281484    function PutAndStream($aImage,$aCacheFileName,$aInline,$aStrokeFileName) {
    2129 
    2130         // Check if we should always stroke the image to a file
    2131         if( _FORCE_IMGTOFILE ) {
    2132             $aStrokeFileName = _FORCE_IMGDIR.GenImgName();
    2133         }
    2134 
    2135         if( $aStrokeFileName != '' ) {
    2136 
    2137             if( $aStrokeFileName == 'auto' ) {
    2138                 $aStrokeFileName = GenImgName();
    2139             }
    2140 
    2141             if( file_exists($aStrokeFileName) ) {
    2142 
    2143                 // Wait for lock (to make sure no readers are trying to access the image)
    2144                 $fd = fopen($aStrokeFileName,'w');
    2145                 $lock = flock($fd, LOCK_EX);
    2146 
    2147                 // Since the image write routines only accepts a filename which must not
    2148                 // exist we need to delete the old file first
    2149                 if( !@unlink($aStrokeFileName) ) {
    2150                     $lock = flock($fd, LOCK_UN);
    2151                     JpGraphError::RaiseL(25111,$aStrokeFileName);
    2152                     //(" Can't delete cached image $aStrokeFileName. Permission problem?");
    2153                 }
    2154                 $aImage->Stream($aStrokeFileName);
    2155                 $lock = flock($fd, LOCK_UN);
    2156                 fclose($fd);
    2157 
    2158             }
    2159             else {
    2160                 $aImage->Stream($aStrokeFileName);
    2161             }
    2162 
    2163             return;
    2164         }
    2165 
    2166         if( $aCacheFileName != '' && USE_CACHE) {
    2167 
    2168             $aCacheFileName = $this->cache_dir . $aCacheFileName;
    2169             if( file_exists($aCacheFileName) ) {
    2170                 if( !$aInline ) {
    2171                     // If we are generating image off-line (just writing to the cache)
    2172                     // and the file exists and is still valid (no timeout)
    2173                     // then do nothing, just return.
    2174                     $diff=time()-filemtime($aCacheFileName);
    2175                     if( $diff < 0 ) {
    2176                         JpGraphError::RaiseL(25112,$aCacheFileName);
    2177                         //(" Cached imagefile ($aCacheFileName) has file date in the future!!");
    2178                     }
    2179                     if( $this->timeout>0 && ($diff <= $this->timeout*60) ) return;
    2180                 }
    2181 
    2182                 // Wait for lock (to make sure no readers are trying to access the image)
    2183                 $fd = fopen($aCacheFileName,'w');
    2184                 $lock = flock($fd, LOCK_EX);
    2185 
    2186                 if( !@unlink($aCacheFileName) ) {
    2187                     $lock = flock($fd, LOCK_UN);
    2188                     JpGraphError::RaiseL(25113,$aStrokeFileName);
    2189                     //(" Can't delete cached image $aStrokeFileName. Permission problem?");
    2190                 }
    2191                 $aImage->Stream($aCacheFileName);
    2192                 $lock = flock($fd, LOCK_UN);
    2193                 fclose($fd);
    2194 
    2195             }
    2196             else {
    2197                 $this->MakeDirs(dirname($aCacheFileName));
    2198                 if( !is_writeable(dirname($aCacheFileName)) ) {
    2199                     JpGraphError::RaiseL(25114,$aCacheFileName);
    2200                     //('PHP has not enough permissions to write to the cache file '.$aCacheFileName.'. Please make sure that the user running PHP has write permission for this file if you wan to use the cache system with JpGraph.');
    2201                 }
    2202                 $aImage->Stream($aCacheFileName);
    2203             }
    2204 
    2205             $res=true;
    2206             // Set group to specified
    2207             if( CACHE_FILE_GROUP != '' ) {
    2208                 $res = @chgrp($aCacheFileName,CACHE_FILE_GROUP);
    2209             }
    2210             if( CACHE_FILE_MOD != '' ) {
    2211                 $res = @chmod($aCacheFileName,CACHE_FILE_MOD);
    2212             }
    2213             if( !$res ) {
    2214                 JpGraphError::RaiseL(25115,$aStrokeFileName);
    2215                 //(" Can't set permission for cached image $aStrokeFileName. Permission problem?");
    2216             }
    2217 
    2218             $aImage->Destroy();
    2219             if( $aInline ) {
    2220                 if ($fh = @fopen($aCacheFileName, "rb") ) {
    2221                     $aImage->Headers();
    2222                     fpassthru($fh);
    2223                     return;
    2224                 }
    2225                 else {
    2226                     JpGraphError::RaiseL(25116,$aFile);//(" Cant open file from cache [$aFile]");
    2227                 }
    2228             }
    2229         }
    2230         elseif( $aInline ) {
    2231             $aImage->Headers();
    2232             $aImage->Stream();
    2233             return;
    2234         }
    2235     }
    2236 
    2237     function IsValid($aCacheFileName) {
    2238         $aCacheFileName = $this->cache_dir.$aCacheFileName;
    2239         if ( USE_CACHE && file_exists($aCacheFileName) ) {
    2240             $diff=time()-filemtime($aCacheFileName);
    2241             if( $this->timeout>0 && ($diff > $this->timeout*60) ) {
    2242                 return false;
    2243             }
    2244             else {
    2245                 return true;
    2246             }
    2247         }
    2248         else {
    2249             return false;
    2250         }
    2251     }
    2252 
    2253     function StreamImgFile($aImage,$aCacheFileName) {
    2254         $aCacheFileName = $this->cache_dir.$aCacheFileName;
    2255         if ( $fh = @fopen($aCacheFileName, 'rb') ) {
    2256             $lock = flock($fh, LOCK_SH);
    2257             $aImage->Headers();
    2258             fpassthru($fh);
    2259             $lock = flock($fh, LOCK_UN);
    2260             fclose($fh);
    2261             return true;
    2262         }
    2263         else {
    2264             JpGraphError::RaiseL(25117,$aCacheFileName);//(" Can't open cached image \"$aCacheFileName\" for reading.");
    2265         }
    2266     }
    2267 
     1485        // Some debugging code to brand the image with numbe of colors
     1486        // used
     1487        GLOBAL $gJpgBrandTiming;
     1488
     1489        if( $gJpgBrandTiming ) {
     1490            global $tim;
     1491            $t=$tim->Pop()/1000.0;
     1492            $c=$aImage->SetColor("black");
     1493            $t=sprintf(BRAND_TIME_FORMAT,round($t,3));
     1494            imagestring($this->img->img,2,5,$this->img->height-20,$t,$c);                       
     1495        }
     1496
     1497        // Check if we should stroke the image to an arbitrary file
     1498        if( _FORCE_IMGTOFILE ) {
     1499            $aStrokeFileName = _FORCE_IMGDIR.GenImgName();
     1500        }
     1501
     1502        if( $aStrokeFileName!="" ) {
     1503            if( $aStrokeFileName == "auto" )
     1504                $aStrokeFileName = GenImgName();
     1505            if( file_exists($aStrokeFileName) ) {
     1506                // Delete the old file
     1507                if( !@unlink($aStrokeFileName) )
     1508                    JpGraphError::RaiseL(25111,$aStrokeFileName);//(" Can't delete cached image $aStrokeFileName. Permission problem?");
     1509            }
     1510            $aImage->Stream($aStrokeFileName);
     1511            return;
     1512        }
     1513
     1514        if( $aCacheFileName != "" && USE_CACHE) {
     1515
     1516            $aCacheFileName = $this->cache_dir . $aCacheFileName;
     1517            if( file_exists($aCacheFileName) ) {
     1518                if( !$aInline ) {
     1519                    // If we are generating image off-line (just writing to the cache)
     1520                    // and the file exists and is still valid (no timeout)
     1521                    // then do nothing, just return.
     1522                    $diff=time()-filemtime($aCacheFileName);
     1523                    if( $diff < 0 )
     1524                        JpGraphError::RaiseL(25112,$aCacheFileName);//(" Cached imagefile ($aCacheFileName) has file date in the future!!");
     1525                    if( $this->timeout>0 && ($diff <= $this->timeout*60) )
     1526                        return;         
     1527                }                       
     1528                if( !@unlink($aCacheFileName) )
     1529                    JpGraphError::RaiseL(25113,$aStrokeFileName);//(" Can't delete cached image $aStrokeFileName. Permission problem?");
     1530                $aImage->Stream($aCacheFileName);       
     1531            }
     1532            else {
     1533                $this->MakeDirs(dirname($aCacheFileName));
     1534                if( !is_writeable(dirname($aCacheFileName)) ) {
     1535                    JpGraphError::RaiseL(25114,$aCacheFileName);//('PHP has not enough permissions to write to the cache file '.$aCacheFileName.'. Please make sure that the user running PHP has write permission for this file if you wan to use the cache system with JpGraph.');
     1536                }
     1537                $aImage->Stream($aCacheFileName);
     1538            }
     1539                       
     1540            $res=true;
     1541            // Set group to specified
     1542            if( CACHE_FILE_GROUP != "" )
     1543                $res = @chgrp($aCacheFileName,CACHE_FILE_GROUP);
     1544            if( CACHE_FILE_MOD != "" )
     1545                $res = @chmod($aCacheFileName,CACHE_FILE_MOD);
     1546            if( !$res )
     1547                JpGraphError::RaiseL(25115,$aStrokeFileName);//(" Can't set permission for cached image $aStrokeFileName. Permission problem?");
     1548                       
     1549            $aImage->Destroy();
     1550            if( $aInline ) {
     1551                if ($fh = @fopen($aCacheFileName, "rb") ) {
     1552                    $this->img->Headers();
     1553                    fpassthru($fh);
     1554                    return;
     1555                }
     1556                else
     1557                    JpGraphError::RaiseL(25116,$aFile);//(" Cant open file from cache [$aFile]");
     1558            }
     1559        }
     1560        elseif( $aInline ) {
     1561            $this->img->Headers();                     
     1562            $aImage->Stream(); 
     1563            return;
     1564        }
     1565    }
     1566       
    22681567    // Check if a given image is in cache and in that case
    22691568    // pass it directly on to web browser. Return false if the
    22701569    // image file doesn't exist or exists but is to old
    2271     function GetAndStream($aImage,$aCacheFileName) {
    2272         if( $this->Isvalid($aCacheFileName) ) {
    2273             $this->StreamImgFile($aImage,$aCacheFileName);
    2274         }
    2275         else {
    2276             return false;
    2277         }
    2278     }
    2279 
     1570    function GetAndStream($aCacheFileName) {
     1571        $aCacheFileName = $this->cache_dir.$aCacheFileName;             
     1572        if ( USE_CACHE && file_exists($aCacheFileName) && $this->timeout>=0 ) {
     1573            $diff=time()-filemtime($aCacheFileName);
     1574            if( $this->timeout>0 && ($diff > $this->timeout*60) ) {
     1575                return false;           
     1576            }
     1577            else {
     1578                if ($fh = @fopen($aCacheFileName, "rb")) {
     1579                    $this->img->Headers();
     1580                    fpassthru($fh);
     1581                    return true;
     1582                }
     1583                else
     1584                    JpGraphError::RaiseL(25117,$aCacheFileName);//(" Can't open cached image \"$aCacheFileName\" for reading.");
     1585            }
     1586        }
     1587        return false;
     1588    }
     1589       
    22801590    //---------------
    2281     // PRIVATE METHODS
     1591    // PRIVATE METHODS 
    22821592    // Create all necessary directories in a path
    22831593    function MakeDirs($aFile) {
    2284         $dirs = array();
    2285         // In order to better work when open_basedir is enabled
    2286         // we do not create directories in the root path
    2287         while ( $aFile != '/' && !(file_exists($aFile)) ) {
    2288             $dirs[] = $aFile.'/';
    2289             $aFile = dirname($aFile);
    2290         }
    2291         for ($i = sizeof($dirs)-1; $i>=0; $i--) {
    2292             if(! @mkdir($dirs[$i],0777) ) {
    2293                 JpGraphError::RaiseL(25118,$aFile);//(" Can't create directory $aFile. Make sure PHP has write permission to this directory.");
    2294             }
    2295             // We also specify mode here after we have changed group.
    2296             // This is necessary if Apache user doesn't belong the
    2297             // default group and hence can't specify group permission
    2298             // in the previous mkdir() call
    2299             if( CACHE_FILE_GROUP != "" ) {
    2300                 $res=true;
    2301                 $res =@chgrp($dirs[$i],CACHE_FILE_GROUP);
    2302                 $res = @chmod($dirs[$i],0777);
    2303                 if( !$res ) {
    2304                     JpGraphError::RaiseL(25119,$aFile);//(" Can't set permissions for $aFile. Permission problems?");
    2305                 }
    2306             }
    2307         }
    2308         return true;
    2309     }
     1594        $dirs = array();
     1595        while ( !(file_exists($aFile)) ) {
     1596            $dirs[] = $aFile;
     1597            $aFile = dirname($aFile);
     1598        }
     1599        for ($i = sizeof($dirs)-1; $i>=0; $i--) {
     1600            if(! @mkdir($dirs[$i],0777) )
     1601                JpGraphError::RaiseL(25118,$aFile);//(" Can't create directory $aFile. Make sure PHP has write permission to this directory.");
     1602            // We also specify mode here after we have changed group.
     1603            // This is necessary if Apache user doesn't belong the
     1604            // default group and hence can't specify group permission
     1605            // in the previous mkdir() call
     1606            if( CACHE_FILE_GROUP != "" ) {
     1607                $res=true;
     1608                $res =@chgrp($dirs[$i],CACHE_FILE_GROUP);
     1609                $res = @chmod($dirs[$i],0777);
     1610                if( !$res )
     1611                    JpGraphError::RaiseL(25119,$aFile);//(" Can't set permissions for $aFile. Permission problems?");
     1612            }
     1613        }
     1614        return true;
     1615    }   
    23101616} // CLASS Cache
    23111617
     1618
    23121619?>
  • trunk/client/modules/Elezioni/grafici/imgdata_balls.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        IMGDATA_ROUNDBALLS.INC
    4 // Description: Base64 encoded images for small round markers
    5 // Created:     2003-03-20
    6 // Ver:         $Id: imgdata_balls.inc.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        IMGDATA_ROUNDBALLS.INC
     4// Description: Base64 encoded images for small round markers
     5// Created:     2003-03-20
     6// Ver:         $Id: imgdata_balls.inc.php 860 2007-03-23 19:16:19Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    1212    protected $name = 'Round Balls';
    1313    protected $an = array(MARK_IMG_LBALL => 'imgdata_large',
    14     MARK_IMG_MBALL => 'imgdata_small',
    15     MARK_IMG_SBALL => 'imgdata_xsmall',
    16     MARK_IMG_BALL => 'imgdata_xsmall');
     14                    MARK_IMG_MBALL => 'imgdata_small',
     15                    MARK_IMG_SBALL => 'imgdata_xsmall',
     16                    MARK_IMG_BALL => 'imgdata_xsmall');
    1717    protected $colors,$index,$maxidx;
    1818    private $colors_1 = array('blue','lightblue','brown','darkgreen',
    19          'green','purple','red','gray','yellow','silver','gray');
     19                              'green','purple','red','gray','yellow','silver','gray');
    2020    private $index_1  = array('blue'=>9,'lightblue'=>1,'brown'=>6,'darkgreen'=>7,
    21          'green'=>8,'purple'=>4,'red'=>0,'gray'=>5,'silver'=>3,'yellow'=>2);
     21                              'green'=>8,'purple'=>4,'red'=>0,'gray'=>5,'silver'=>3,'yellow'=>2);
    2222    private $maxidx_1 = 9 ;
    2323
    2424    private $colors_2 = array('blue','bluegreen','brown','cyan',
    25      'darkgray','greengray','gray','green',
    26      'greenblue','lightblue','lightred',
    27      'purple','red','white','yellow');
    28     
    29 
     25                          'darkgray','greengray','gray','green',
     26                          'greenblue','lightblue','lightred',
     27                          'purple','red','white','yellow');
     28                         
     29       
    3030    private $index_2 =  array('blue'=>9,'bluegreen'=>13,'brown'=>8,'cyan'=>12,
    31      'darkgray'=>5,'greengray'=>6,'gray'=>2,'green'=>10,
    32      'greenblue'=>3,'lightblue'=>1,'lightred'=>14,
    33      'purple'=>7,'red'=>0,'white'=>11,'yellow'=>4);
    34      
     31                          'darkgray'=>5,'greengray'=>6,'gray'=>2,'green'=>10,
     32                          'greenblue'=>3,'lightblue'=>1,'lightred'=>14,
     33                          'purple'=>7,'red'=>0,'white'=>11,'yellow'=>4);
     34                       
    3535    private $maxidx_2 = 14 ;
    3636
    3737
    3838    private $colors_3 = array('bluegreen','cyan','darkgray','greengray',
    39      'gray','graypurple','green','greenblue','lightblue',
    40      'lightred','navy','orange','purple','red','yellow');
    41 
     39                          'gray','graypurple','green','greenblue','lightblue',
     40                          'lightred','navy','orange','purple','red','yellow');
     41       
    4242    private $index_3 = array('bluegreen'=>1,'cyan'=>11,'darkgray'=>14,'greengray'=>10,
    43     'gray'=>3,'graypurple'=>4,'green'=>9,'greenblue'=>7,
    44     'lightblue'=>13,'lightred'=>0,'navy'=>2,'orange'=>12,
    45     'purple'=>8,'red'=>5,'yellow'=>6);
     43                        'gray'=>3,'graypurple'=>4,'green'=>9,'greenblue'=>7,
     44                        'lightblue'=>13,'lightred'=>0,'navy'=>2,'orange'=>12,
     45                        'purple'=>8,'red'=>5,'yellow'=>6);
    4646    private $maxidx_3 = 14 ;
    4747
     
    5050
    5151    function GetImg($aMark,$aIdx) {
    52         switch( $aMark ) {
    53             case MARK_IMG_SBALL:
    54             case MARK_IMG_BALL:
    55                 $this->colors = $this->colors_3;
    56                 $this->index = $this->index_3 ;
    57                 $this->maxidx = $this->maxidx_3 ;
    58                 break;
    59             case MARK_IMG_MBALL:
    60                 $this->colors = $this->colors_2;
    61                 $this->index = $this->index_2 ;
    62                 $this->maxidx = $this->maxidx_2 ;
    63                 break;
    64             default:
    65                 $this->colors = $this->colors_1;
    66                 $this->index = $this->index_1 ;
    67                 $this->maxidx = $this->maxidx_1 ;
    68                 break;
    69         }
    70         return parent::GetImg($aMark,$aIdx);
     52        switch( $aMark ) {
     53            case MARK_IMG_SBALL:
     54            case MARK_IMG_BALL:
     55                $this->colors = $this->colors_3;
     56                $this->index = $this->index_3 ;
     57                $this->maxidx = $this->maxidx_3 ;
     58                break;
     59            case MARK_IMG_MBALL:
     60                $this->colors = $this->colors_2;
     61                $this->index = $this->index_2 ;
     62                $this->maxidx = $this->maxidx_2 ;
     63                break;
     64            default:
     65                $this->colors = $this->colors_1;
     66                $this->index = $this->index_1 ;
     67                $this->maxidx = $this->maxidx_1 ;
     68                break;
     69        }
     70        return parent::GetImg($aMark,$aIdx);
    7171    }
    7272
    73     function __construct() {
    74 
    75         //==========================================================
    76         // File: bl_red.png
    77         //==========================================================
    78         $this->imgdata_large[0][0]= 1072 ;
    79         $this->imgdata_large[0][1]=
    80      'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAByF'.
    81      'BMVEX/////////xsb/vb3/lIz/hIT/e3v/c3P/c2v/a2v/Y2P/'.
    82      'UlL/Skr/SkL/Qjn/MTH/MSn/KSn/ISH/IRj/GBj/GBD/EBD/EA'.
    83      'j/CAj/CAD/AAD3QkL3MTH3KSn3KSH3GBj3EBD3CAj3AAD1zMzv'.
    84      'QkLvISHvIRjvGBjvEBDvEAjvAADnUlLnSkrnMTnnKSnnIRjnGB'.
    85      'DnEBDnCAjnAADec3PeSkreISHeGBjeGBDeEAjWhITWa2vWUlLW'.
    86      'SkrWISnWGBjWEBDWEAjWCAjWAADOnp7Oa2vOGCHOGBjOGBDOEB'.
    87      'DOCAjOAADJrq7Gt7fGGBjGEBDGCAjGAADEpKS/v7+9QkK9GBC9'.
    88      'EBC9CAi9AAC1e3u1a2u1Skq1KSm1EBC1CAi1AACtEBCtCBCtCA'.
    89      'itAACngYGlCAilAACghIScOTmcCAicAACYgYGUGAiUCAiUAAiU'.
    90      'AACMKSmMEACMAACEa2uEGAiEAAB7GBh7CAB7AABzOTlzGBBzCA'.
    91      'BzAABrSkprOTlrGBhrAABjOTljAABaQkJaOTlaCABaAABSKSlS'.
    92      'GBhSAABKKSlKGBhKAABCGBhCCABCAAA5CAA5AAAxCAAxAAApCA'.
    93      'ApAAAhAAAYAACc9eRyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
    94      'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFD'.
    95      'UHLytKAAAB4UlEQVR4nGNgIAK4mGjrmNq6BmFIWMmISUpKSmk5'.
    96      'B8ZEokj4qoiLiQCBgqald3xaBpKMj6y4sLCQkJCIvIaFV0RaUR'.
    97      'lCSk5cWEiAn19ASN7QwisuraihHiajKyEixM/NwckjoKrvEACU'.
    98      'qumpg7pAUlREiJdNmZmLT9/cMzwps7Smc3I2WEpGUkxYkJuFiY'.
    99      'lTxszePzY1v7Shc2oX2D+K4iLCgjzsrOw8embuYUmZeTVtPVOn'.
    100      'gqSslYAOF+Ln4ZHWtXMPTcjMrWno7J82rRgoZWOsqaCgrqaqqm'.
    101      'fn5peQmlsK1DR52vRaoFSIs5GRoYG5ub27n19CYm5pdVPnxKnT'.
    102      'pjWDpLydnZwcHTz8QxMSEnJLgDL9U6dNnQ6Sio4PDAgICA+PTU'.
    103      'zNzSkph8hADIxKS46Pj0tKTc3MLSksqWrtmQySAjuDIT8rKy0r'.
    104      'Kz+vtLSmur6jb9JUIJgGdjxDQUVRUVFpaUVNQ1NrZ9+kKVOmTZ'.
    105      'k6vR0sldJUAwQNTU2dnX0TgOJTQLrSIYFY2dPW1NbW2TNxwtQp'.
    106      'U6ZMmjJt2rRGWNB3TO7vnzh5MsgSoB6gy7sREdY7bRrQEDAGOb'.
    107      'wXOQW0TJsOEpwClmxBTTbZ7UDVIPkp7dkYaYqhuLa5trYYUxwL'.
    108      'AADzm6uekAAcXAAAAABJRU5ErkJggg==' ;
    109 
    110         //==========================================================
    111         // File: bl_bluegreen.png
    112         //==========================================================
    113         $this->imgdata_large[1][0]= 1368 ;
    114         $this->imgdata_large[1][1]=
    115      'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'.
    116      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
    117      'B3RJTUUH0wMMFi8hE9b2uAAABOVJREFUeNq9lk2sJFUVx3+3qv'.
    118      'tW95t57zFvhiFxmCFRUJRoNCQiJARMhiFx/Igxii5goTG6ZDAu'.
    119      '/EhcSCIrTAgLEiKsJ8ywABNZEMJXEDYCukAmjgjzBkK/j35V1d'.
    120      '333FtV97io97pfzwxfG86qcu/N+Z3zP+fcW/Apmfk4hx57+R/6'.
    121      'Rqmc9ykhsWjlsUngAA1fXIQ7b73pI/186IGHnn9dH/8frC8v4I'.
    122      'PiG53uaerR4GmKkv31mB8cyfjd946ZTwR66qVX9OTWIi8UKUv9'.
    123      'BOrZXpYZvFeiBvzI0fgSUSFKwbVG+Pl1V3HH0VvNR4KeeukV/f'.
    124      'PmMmdHhst76aXD64AbeVQ9bjNHaiGOC2o3wLrAb2/4LL/84ffn'.
    125      'fCdzkOdayKpLppBemrBsU5Y1Zdmm9LJdGU6E/t4M24Q26jRDRL'.
    126      'j3mdc49cSTekFsMzs5XuTsyLDUNSDQ25NwKOly9YIl22MYhJr/'.
    127      'uoDtBBoT0CxBRGYOAhibIaOCe//2MpfM6KHnX9cXipSlbkKWmS'.
    128      'nk9iv38J0jixw7vJfrTMYBOvhSoQHJBS09ANELloAGDxW8tfoW'.
    129      'J+5/UC8CPS0LU7r3SpYarr7M8rmFjMPLXT6/33L4si7Z2GCrQC'.
    130      '+0ctlOaNs9DReV8vSLr85ndPLpZ/WNvHW+01kAVFBOGvJx0wYg'.
    131      'Sp47RIQ4Emwa8FGJXlDxSCFo5YlVgAo2hwPue/hRndboTV3EW2'.
    132      'Wp3k6wBp8q56QiWzecW6vwQfnPRkAWhFgILnq08jQ+R2nlUzzN'.
    133      'uES9Q7Vd+9fba7NmWJW61db2247qACmcjxXr45psYphsFGSLBu'.
    134      'kIajxqtjNwHkvAjQt0sg3crhPA2+fPz0CuyNFOghsGsr19mnFg'.
    135      'DGwrRm8UoAtNmQPQtRXDgdC4HImCFEKcCE0oieUWUYq2LtbiGp'.
    136      'mBQmppfIkjw45DK0QNNkvQ0jMBtPL0UnDRM1rN+cxKwzvOo2NP'.
    137      'tykR9a1kfpZNDLMG6QDYJqCTBvUe1+uxs+YKyPoGrTwY2HhvC4'.
    138      'CDWQd5d4xNApNQEEMgjgLdUCLBQ5cprL/trwNwKG2IUmDqDFd5'.
    139      'sr5BWrlxuSdLDFEFlqAzXGc4zFjupqh6uqYihpxJcEgp026l2w'.
    140      '7wFUv7Z6AvrfRo/n0OYzPwIKE3HUKAJg2otMBiElnsF7wngis9'.
    141      '3ZDjNnLi7huCWUZfueZKTu/M0V3HvmkOFDVxVKDG04ScejSgW5'.
    142      'V0q5JYFEghuDLHlTmToqDeGOCKIVtrW9hsdmXufEcNLPSXuPHa'.
    143      'a+bvuh9df5AH/v5PDFmbWQC3Mx+TVvfGVTRB2CodNgT2JBX003'.
    144      'aANZAYS/BxCv32TV/l2C03G7jgmfjGiT/qmeEmibEYm7XzAO2k'.
    145      'A+pbgHhBgydqu54YO5eRiLCy7yDvPP6Xqf+5Z+Lu277OYuOpiw'.
    146      'H15oBmlNOMcmK5RbP+PrEscGU+DSAxdg4CICIkxnLP8aNz63Og'.
    147      'H3/rdvOb795GVhuaYo0oBc3GGrEsUPVTwO6a7LYd+X51x3Hu/t'.
    148      'lP5tS65FN+6okn9U+n/sqb596dTvhOF+02myXTmkQNrOw7yD3H'.
    149      'j14E+UDQjp24/0E9/eKrbA4HH3aMK1b2ccvXvswjv//1J/s5ud'.
    150      'Due/hRPfP+OmfOrk7vrn7a48ihA3zh8CH+8Iuffiw/n4r9H1ZZ'.
    151      '0zz7G56hAAAAAElFTkSuQmCC' ;
    152 
    153         //==========================================================
    154         // File: bl_yellow.png
    155         //==========================================================
    156         $this->imgdata_large[2][0]= 1101 ;
    157         $this->imgdata_large[2][1]=
    158      'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'.
    159      'BMVEX//////////+///+f//9b//8b//73//7X//63//6X//5T/'.
    160      '/4z//4T//3P//2v//1r//0r//0L//zH//yn//yH//xj//xD//w'.
    161      'j//wD/90L/9zn/9zH/9xj/9xD/9wj/9wD39yn37zn37zH37yH3'.
    162      '7xD37wj37wDv70Lv50rv50Lv5znv5yHv5xjv5wjv5wDn51Ln5x'.
    163      'Dn3jHn3iHn3hjn3hDn3gje3oze3nPe3lLe1oze1nPe1lLe1ine'.
    164      '1iHe1hje1hDe1gje1gDW1qXW1mvWzqXWzkLWzhjWzhDWzgjWzg'.
    165      'DOzrXOzq3OzpzOzgDOxkrOxinOxhjOxhDOxgjOxgDGxqXGxnvG'.
    166      'xmvGvRjGvRDGvQjGvQDFxbnAvr6/v7+9vaW9vZS9vQi9vQC9tR'.
    167      'C9tQi9tQC7u7W1tZS1tXu1tTG1tQi1rRC1rQi1rQCtrYytrSGt'.
    168      'rQitrQCtpYStpSGtpQitpQClpYSlpXulpQClnBClnAilnACcnG'.
    169      'ucnAicnACclAiclACUlFqUlCmUlAiUlACUjFKUjAiUjACMjFKM'.
    170      'jEqMjACMhACEhACEewB7ezF7exB7ewB7cwBzcylzcwBzaxBzaw'.
    171      'BraxhrawhrawBrYxBrYwBjYwBjWgBaWgBaUgCXBwRMAAAAAXRS'.
    172      'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'.
    173      'LdfvwAAAAHdElNRQfTAwkRFBKiJZ4hAAAB7ElEQVR4nI3S+1vS'.
    174      'UBgHcB67WJmIMWAVdDHEDLBC6Go0slj3Ft0m9RRBWQEmFZFDEM'.
    175      'Qgt0EMFBY7p/+198hj1kM/9N1+++x73rOd6XT/kStnTx4fPzd9'.
    176      'uwfOjFhomj7smAhwj/6Cm2O0xUwy6g7cCL99uCW3jtBmE7lsdr'.
    177      'fvejgpzP7uEDFRRoqy2k8xQPnypo2BUMP6waF9Vpf3ciiSzErL'.
    178      'XTkPc0zDe3bsHDAcc00yoVgqL3UWN2iENpspff+2vn6D0+NnZ9'.
    179      '6lC5K6RuSqBTZn1O/a3rd7v/MSez+WyIpVFX8GuuCA9SjD4N6B'.
    180      'oRNTfo5PCAVR0fBXoIuOQzab1XjwwNHx00GOj8/nKtV1DdeArk'.
    181      '24R+0ul9PjmbrHPYl+EipyU0OoQSjg8/m83kl/MMhx0fjCkqio'.
    182      'SMOE7t4JMAzDsizH81AqSdW2hroLPg4/CEF4PhKNx98vlevrbY'.
    183      'QQXgV6kXwVfjkTiSXmhYVcSa7DIE1DOENe7GM6lUym0l+EXKks'.
    184      'K20VAeH2M0JvVgrZfL5Qqkiy0lRVaMBd7H7EZUmsiJJcrTdVja'.
    185      'wGpdbTLj3/3qwrUOjAfGgg4LnNA5tdQx14Hm00QFBm65hfNzAm'.
    186      '+yIFhFtzuj+z2MI/MQn6Uez5pz4Ua41G7VumB/6RX4zMr1TKBr'.
    187      'SXAAAAAElFTkSuQmCC' ;
    188 
    189         //==========================================================
    190         // File: bl_silver.png
    191         //==========================================================
    192         $this->imgdata_large[3][0]= 1481 ;
    193         $this->imgdata_large[3][1]=
    194      'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAADAF'.
    195      'BMVEUAAADOzs7Gxsa9vb21tbXOxsbOzsbGzsb3///O1ta1vb2c'.
    196      'paVSWlpKWlpSY2ve5+97hIze7/9aY2vO5/9zhJRaa3tSY3PGzt'.
    197      'aMlJxrc3tja3NKUlpCSlK1vcZze4RSWmPW5/+Upb3G3v9zhJxS'.
    198      'Y3t7jKVaa4TO3veltc6ElK1re5Rjc4ycpbV7hJRaY3M5QlLn7/'.
    199      '/Gzt6lrb2EjJzO3v9ja3vG1ve9zu+1xueltdacrc6UpcaMnL1C'.
    200      'SlqElLV7jK1zhKVre5zW3u/O1ue1vc6ttcaMlKVze4xrc4RSWm'.
    201      'tKUmPG1v+9zve1xu+tveeltd6crdbe5/+9xt6cpb17hJxaY3s5'.
    202      'QlrW3vfO1u/Gzue1vdattc6lrcaUnLWMlK2EjKVze5Rrc4xja4'.
    203      'RSWnNKUmtCSmO9xuecpcZ7hKVaY4TW3v/O1vfGzu+1vd6ttdal'.
    204      'rc69xu+UnL2MlLWEjK1ze5xrc5R7hK1ja4zO1v+1veettd6lrd'.
    205      'aMlL3Gzv/39//W1t7Gxs61tb29vcatrbWlpa2cnKWUlJyEhIx7'.
    206      'e4TW1ufGxta1tcZSUlqcnK3W1u+UlKW9vda1tc57e4ytrcalpb'.
    207      '1ra3vOzu9jY3OUlK29vd6MjKWEhJxaWmtSUmNzc4xKSlpjY3tK'.
    208      'SmNCQlqUjJzOxs7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
    209      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
    210      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
    211      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
    212      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
    213      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
    214      'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
    215      'AAAAAAAAAAAAAAAAAAAAAAAAD///9fnkWVAAAAAnRSTlP/AOW3'.
    216      'MEoAAAABYktHRP+lB/LFAAAACXBIWXMAAABFAAAARQBP+QatAA'.
    217      'AB/klEQVR42mNgxAsYqCdd3+lcb4hLmj8wMMvEu8DCMqYbU9op'.
    218      'UEFB2MTb26eyysomFl06XEEhUCHLpAKo2z/fujikEUVaXUFBMB'.
    219      'BouLePuV+VVWGRciIXknSEsImCQd3//xwmPr65llaFcSFJHkjS'.
    220      '3iYmWUDZ//8NfCr989NjNUMSUyTg0jneSiaCINn/gmlVQM12qg'.
    221      'lJnp5waTMTE5NAkCyHWZW/lXWNfUlikmdYK0zax7siS4EDKJtd'.
    222      'mQeU1XRwLBdLkRGASucWmGVnZ4dnhZvn5lmm29iVOWpnJqcuko'.
    223      'JKR1Wm5eTkRKYF5eblp9sU2ZeUJiV7zbfVg0pH56UFBQXNjIqK'.
    224      'jgkujItX1koKTVmYajsdKu2qETVhwgSXiUDZ2Bn9xqUeoZ5e0t'.
    225      'LzYYZ3B092ndjtOnmKTmycW1s7SHa+l5dtB8zlccE6RlN0dGbM'.
    226      'mDVbd5KupNBcL6+F82XgHouLj5vRP2PWLGNdd4+ppnxe8tJec6'.
    227      'XnNsKkm0uVQ5RDRHQTPTym68nPlZbvkfYCexsa5rpJ2qXa5Umm'.
    228      'ocmec3m8vHjmSs+fgxyhC5JDQ8WSPT2lvbzm8vDIe0nbtiBLN8'.
    229      '8BigNdu1B6Lsje+fPbUFMLi5TMfGmvHi/puUAv23q2YCTFNqH5'.
    230      'MvPnSwPh3HasCbm3XUpv+nS5VtrkEkwAANSTpGHdye9PAAAASn'.
    231      'RFWHRzaWduYXR1cmUANGJkODkyYmE4MWZhNTk4MTIyNDJjNjUx'.
    232      'NzZhY2UxMDAzOGFhZjdhZWIyNzliNTM2ZGFmZDlkM2RiNDU3Zm'.
    233      'NlNT9CliMAAAAASUVORK5CYII=' ;
    234 
    235         //==========================================================
    236         // File: bl_purple.png
    237         //==========================================================
    238         $this->imgdata_large[4][0]= 1149 ;
    239         $this->imgdata_large[4][1]=
    240      'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACAV'.
    241      'BMVEX/////////7///5///1v//xv//rf//pf//lP//jP//hP//'.
    242      'c///a///Wv//Wvf/Uv//Sv//Qv//Qvf/Off/Mf//Kf//If//If'.
    243      'f/GP//GPf/EP//EPf/CP//CPf/CO//AP//APf3Oe/3Kff3Ke/3'.
    244      'Ie/3GO/3EO/3AO/vSu/vSufvOefvMefvIefvGOfvEOfvCOfvAO'.
    245      'fnUufnSufnMd7nId7nGN7nGNbnEN7nCN7nAN7ejN7ejNbec97e'.
    246      'c9beUtbeQtbeIdbeGNbeENbeCNbeANbWpdbWa9bWQs7WGM7WEM'.
    247      '7WCM7WAM7Otc7Orc7OnM7OSsbOIb3OGMbOEMbOCMbOAM7OAMbG'.
    248      'pcbGnMbGe8bGa8bGKbXGEL3GCL3GAL3FucXBu73AvsC/v7+9pb'.
    249      '29Ka29GLW9ELW9CLW9AL29ALW5rrm1lLW1e7W1MbW1GKW1EK21'.
    250      'CLW1CK21AK2tjK2thKWtMaWtIaWtGJytCK2tCKWtAK2tAKWlhK'.
    251      'Wle6WlEJylCJylAKWlAJyca5ycGJScEJScCJScAJycAJSUWpSU'.
    252      'UoyUKZSUEIyUCIyUAJSUAIyMUoyMSoyMIYSMEISMCISMAIyMAI'.
    253      'SECHuEAISEAHt7MXt7EHt7CHt7AHt7AHNzKXNzEGtzAHNzAGtr'.
    254      'GGtrEGNrCGtrAGtrAGNjCFpjAGNjAFpaAFpaAFIpZn4bAAAAAX'.
    255      'RSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsS'.
    256      'AdLdfvwAAAAHdElNRQfTAwkRFB0ymoOwAAAB9UlEQVR4nGNgIA'.
    257      'K42hhqGtm5+WFIWClKycvLK6gbuARGoEj4aMjLSElISUir6Tt7'.
    258      'x+aEIWR8leQlwEBSTc/CK7awLguuR0lGQkJMVFRUTFJVzwko1d'.
    259      'oFk9OQl5IQE+Dh5hVR0TV3CkkvbJgyASJjDZIR5GBl5eRX0TH1'.
    260      'DEqrbJ2ypBEspSgvJSXKw8bMxMavbOLoGZNf1TZlybw4oIyfLN'.
    261      'BxotxsLEzsQiaOHkFpBQ2905esrAZK2SpIAaUEuDm5+LTNPAKj'.
    262      'C+pbps1evrIDKGWnLictKSkuLKyoZQyUya9o7Z2+YMXKGUApew'.
    263      'M9PTVdXR0TEwf3wOjUirruafOXL18xFyjl72Kpb25qaurg4REU'.
    264      'EFVe2zJ5zpLlK1aCpbydnZ2dnDwDA6NTopLLeiZNXbB8BcTAyP'.
    265      'TQ0JDg4KCY1NS83JKmiVOBepYvX9UPlAovzEiPSU/LLyior2vq'.
    266      'mjZr3vLlIF01IC+XVhUWFlZW1Lc290ycOGfxohVATSsXx4Oksn'.
    267      'vaWlsb2tq6J0+bM2/RohVA81asbIcEYueU3t7JU6ZNnwNyGkhm'.
    268      '+cp5CRCppJnzZ8+ZM3/JUogECBbBIixr8Yqly8FCy8F6ltUgoj'.
    269      'lz7sqVK2ByK+cVMSCDxoUrwWDVysXt8WhJKqG4Y8bcuTP6qrGk'.
    270      'QwwAABiMu7T4HMi4AAAAAElFTkSuQmCC' ;
    271 
    272         //==========================================================
    273         // File: bl_gray.png
    274         //==========================================================
    275         $this->imgdata_large[5][0]= 905 ;
    276         $this->imgdata_large[5][1]=
    277      'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAABO1'.
    278      'BMVEX////////3///39/fv7+/e5+fW3t7Wzs7WxsbG1tbGzsbG'.
    279      'xsbDxMS/v7++wMC+v7+9zsa9xsa9vb29tbW9ra29pa24uLi1xs'.
    280      'a1vb21tbWxtrattbWmpqalra2cra2cpaWcnJycjIyUpaWUnJyU'.
    281      'lJSUjIyMnJyMnJSMlJSMlIyMjJSMjIyElJSElIyEjIyEhIR7jI'.
    282      'x7hIR7hHt7e3t7e3N7e2tzhIRze3tze3Nzc3Nre3trc3Nrc2tr'.
    283      'a2tjc3Njc2tja3Nja2tjY2NjWlpaa2taY2taY2NaY1paWlpaUl'.
    284      'JSY2NSY1pSWlpSWlJSUlJSUkpKWlpKWlJKUlpKUlJKUkpKSkpK'.
    285      'SkJCUlJCUkJCSkpCSkJCQkI5Sko5QkI5Qjk5OUI5OTkxQkIxOT'.
    286      'kxMTkxMTEpMTEhMTEhKSkYISEpy7AFAAAAAXRSTlMAQObYZgAA'.
    287      'AAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdE'.
    288      'lNRQfTAwkRFQfW40uLAAABx0lEQVR4nI3SbXfSMBQA4NV3nce5'.
    289      'TecAHUywRMHSgFuBCFsQUqwBS1OsWQh0GTj//y8wZUzdwQ/efM'.
    290      'tzcm/uuXdj4z9ic/PR9k4qk1qDnf0X2/uZzKt8GaRvSubg4LVp'.
    291      'mkWzCGAT/i3Zsm2XNQHLsm2n2937LaaNnGoJFAEo27B50qN0ay'.
    292      'Wg26lXsw8fP8nmzcJb2CbsnF5JmmCE8ncN404KvLfsYwd7/MdV'.
    293      'Pdgl/VbKMIzbuwVgVZw2JlSKJTVJ3609vWUY957lgAUd1KNcqr'.
    294      'yWnOcOPn8q7d5/8PywAqsOOiVDrn42NFk+HQ7dVuXNYeFdBTpN'.
    295      'nY5JdZl8xI5Y+HXYaTVqEDp1hAnRohZM03EUjMdhn5wghOoNnD'.
    296      'wSK7KiiDPqEtz+iD4ctdyAifNYzUnScBSxwPd6GLfRURW7Ay5i'.
    297      'pS5bmrY8348C5vvUI+TLiIVSJrVA0heK/GDkJxYMRoyfCSmk4s'.
    298      'uWc3yic/oBo4yF374LGQs5Xw0GyQljI8bYmEsxVUoKxa6HMpAT'.
    299      'vgyhU2mR8uU1pXmsa8ezqb6U4mwWF/5MeY8uLtQ0nmmQ8UWYvb'.
    300      'EcJaYWar7QhztrO5Wr4Q4hDbAG/4hfTAF2iCiWrCEAAAAASUVO'.
    301      'RK5CYII=' ;
    302 
    303         //==========================================================
    304         // File: bl_brown.png
    305         //==========================================================
    306         $this->imgdata_large[6][0]= 1053 ;
    307         $this->imgdata_large[6][1]=
    308      'iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAABoV'.
    309      'BMVEX////Gzs7GvbXGrZTGpXu9nHO1nHO1nIy9taXGxs7GtaXO'.
    310      'nHPGlFrGjEq9hEq1hEqte0Klczmcazmce1KtnIzGxsbGvb3OlF'.
    311      'LOlFq9hFKte0qcc0KUYzGEWimMc1K9ta3OnGvOnGPWnGO9jFq9'.
    312      'jFKlc0KUazmMYzl7UilzUjGtpZzGxr3GnGPWpWvepXO1hFJ7Wj'.
    313      'FrSiFjUjG1ra3GnHPvxpT/5733zpythFKUa0KEYzlzUilaOSF7'.
    314      'Wjm9jErvvYz/99b///f/78bnrYS1hFqle0p7UjFrSiljQiFCMR'.
    315      'iMhHO9lGvGjFLWnGv/3q3////erXuthEqlc0paQiFKMRhSQin/'.
    316      '1qX/997//++cc0pjSilaQilKORhCKRiclIy9pYzGlGPntYT33q'.
    317      '3vvZSEWjlSOSE5KRB7c2O1lHutczmthFqte1JrWkqtjGtCKRBa'.
    318      'SjmljGuca0KMYzGMaznOztaclISUYzmEWjFKOSF7a1qEYzFaSi'.
    319      'GUjISEa0pKOSm9vb2llIxaQhg5IQiEc2tzY0paORilnJy1raVS'.
    320      'OSljUkJjWkKTpvQWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'.
    321      'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkREiei'.
    322      'zP2EAAAB9UlEQVR4nGWS/VfSUBjHL5QluhhBxtwyWcCus5Blpm'.
    323      'wDC4ONaWXCyBi7RMZmpQ2Bypm9W/byV3cHHo/W88s95/s5z/d5'.
    324      'uwCcCh/4L3zAf+bs0NC588On9QAYGSUuBINk6GI4cmnsBLk8Go'.
    325      '1SFEGMkzRzZeLq5JE8FvDHouw1lqXiCZJOcnCKnx4AcP0GBqmZ'.
    326      'mRgRT9MMB4Wbs7cGSXNRik3dnp9fiMUzNCNKgpzN9bsaWaQo9s'.
    327      '7dfH7pXiFTZCBU1JK27LmtBO8TDx7mV1eXHqXXyiIUFLWiVzHx'.
    328      'BxcJIvV4/cn6wkqmWOOwmVE3UQOAp6HxRKL5bGPj+VwhUhalFq'.
    329      '8alm5vAt+LlySZTsebzcKrraIIW4JqZC3N3ga+1+EQTZKZta1M'.
    330      'pCZCSeDViqVrThsEdsLJZLJYLpZrHVGScrKBvTQNtQHY6XIM02'.
    331      'E6Ik7odRW1Dzy3N28n3kGuB3tQagm7UMBFXI/sATAs7L5vdbEs'.
    332      '8Lycm923NB0j5wMe6KOsKIIyxcuqauxbrmlqyEWfPmPy5assY1'.
    333      'U1SvWKZWom9nK/HfQ3+v2HYZSMStayTNN0PYKqg11P1nWsWq7u'.
    334      '4gJeY8g9PLrddNXRdW8Iryv86I3ja/9s26gvukhDdvUQnIjlKr'.
    335      'IdZCNH+3Xw779qbG63f//ZOzb6C4+ofdbzERrSAAAAAElFTkSu'.
    336      'QmCC' ;
    337 
    338         //==========================================================
    339         // File: bl_darkgreen.png
    340         //==========================================================
    341         $this->imgdata_large[7][0]= 1113 ;
    342         $this->imgdata_large[7][1]=
    343      'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'.
    344      'BMVEX////////3///v///n/+/e99bW/+/W99bO786/v7++vr69'.
    345      '/96999a7wb24vbu1/9a1zqW1u7itxrWosq6l772l1qWlxrWlxq'.
    346      '2lva2cxpSU562U3q2UxqWUvaWUpZyM77WM57WMvYyMtZyMrZyM'.
    347      'pZSMnJSEvZyEtYyErZSElIx7zpR7xpx7xpR7vZR7jIRz1pRzxp'.
    348      'RzjIRrzpRrzoxrxoxrtYRrrYxrrXtrpYRrhHNjzoxjxoxjxoRj'.
    349      'vYRjtYRjrXtjpXtjlGNje2tazoxazoRaxoxaxoRavYRatYRatX'.
    350      'tarXtapXNanHNajFpae2tSzoRSxoRSvXtStXtSrXtSrXNSpXNS'.
    351      'nHNSnGtSlGtSlGNSjGtSjGNKvXtKtXNKrXNKpWtKnGtKlGNKjG'.
    352      'NKhGNKhFJKc1pKa1JCrWtCpWtCnGtClGNCjGNCjFpChFpCe1JC'.
    353      'a1JCY1I5pWs5nGM5lGM5jFo5hFo5e1o5c0o5WkoxjFoxhFoxhF'.
    354      'Ixe1Ixc1Ixc0oxa0ophFIpe0opc0opa0opa0IpY0IpWkIpWjkp'.
    355      'UkIpUjkhc0oha0IhY0IhWjkhWjEhUjkhUjEhSjEhSikhQjEhQi'.
    356      'kYWjkYSjEYSikYQjEYQikQSikQQikQQiEQOSExf8saAAAAAXRS'.
    357      'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'.
    358      'LdfvwAAAAHdElNRQfTAwkRFCaDkWqUAAAB+ElEQVR4nI3S+1vS'.
    359      'UBgHcGZlPV0ks/vFrmQWFimJjiwiYUJWjFBWFhClyZCy5hLrwA'.
    360      'x2EIwJC1w7zf2vnU0re+iHvs9++7x7zznvORbLf+TA6ct9fYMX'.
    361      'jrfAUYefpp+/iM1ykxf/lmuhUZ/PTwXC8dml5Wcd23o5H5Mk6b'.
    362      '5NUU8icXbhS67rNzn9JDnguOEYGQtEEtwC+Crs3RJ76P5A/znr'.
    363      'vsNX7wQnEiwHCtK7TTkW8rvdZ9uJtvZTLkxpHhSrP66bNEj7/P'.
    364      '3WNoLYeeSWQQCIpe9lQw7RNEU5rDsIYtcJ14Nocg7kRUlBNkxn'.
    365      'YmGKcp7cv3vPwR7XOJPmc0VYU3Sv0e9NOBAYG7Hbz/cMjTMveZ'.
    366      'CHkqxuTBv0PhYJB4N3XR6PJ5rMAPMnpGUxDX1IxSeMTEaZp1OZ'.
    367      'nGAIQiYtsalUIhFlmGTy3sO3AizJCKn6DKYryxzHsWyaneMzr6'.
    368      'cWxRVZVlFTe4SpE3zm+U/4+whyiwJcWVMQNr3XONirVWAklxcE'.
    369      'EdbqchPhjhVzGpeqhUKhWBQhLElr9fo3pDaQPrw5xOl1CGG1JE'.
    370      'k1uYEBIVkrb02+o6RItfq6rBhbw/tuINT96766KhuqYpY3UFPF'.
    371      'BbY/19yZ1XF1U0UNBa9T7rZsz80K0jWk6bpWGW55UzbvTHZ+3t'.
    372      'vbAv/IT+K1uCmhIrKJAAAAAElFTkSuQmCC' ;
    373 
    374         //==========================================================
    375         // File: bl_green.png
    376         //==========================================================
    377         $this->imgdata_large[8][0]= 1484 ;
    378         $this->imgdata_large[8][1]=
    379      'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'.
    380      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
    381      'B3RJTUUH0wMMFjM4kcoDJQAABVlJREFUeNq9ll2MJFUVx3/11V'.
    382      'Vd/TE9vU0v4zLDwJIF16jBqLAPhsRXEiDqg0QTJiQSjcSNvCzw'.
    383      'sBEDDxizhvAAxBgf1oR9QF9NiE9ESFZkQyZB5WtddmdnZ3qqqr'.
    384      'uqbt367Cofqu3ZZpWVaDzJfbkf53//55z/PVdZXV3l/2H6f7Lp'.
    385      '5VdOV/4Nb+GmHpUeA7AdBNxc3kafNb73jRPK9Xwon8ToxVefqU'.
    386      'b91wibH5EkCQBCizFihTSviHUHR0hWws9xe3wvJ7/7nPKpgX5y'.
    387      '9oFqt3eOgWniRBoAbUBGGqZUibSYaeoT2B5bnkdaSA6793Cv/S'.
    388      'QPPbihXBfo5VdOV+8dfgnvwAU62YH5fCZ12sDujFkwyegCqTrB'.
    389      'iUOKTOJKj8jr88jS8zy6cXwBTP048nuHX0I0nDlIp7RpTG7kM0'.
    390      'sdyAYsTVukUuWGhlWHMq0ITL92lnUp9R1Obz/GmTNnqn9bDD8/'.
    391      '+0D1oX0O0zQZZDYCsK2j3Gl9jQqDfHiei8GfiKVLlsZkJaBAN1'.
    392      '0i6PgwUbB0GxG5/PrtE/xLRr959Znqw9452oVNI+jiJhnr1pe4'.
    393      'k29zB1/nFr5Kj7tpt1YYhJ0FJ7nUYbcJQBgahN2MzeCP/OipR6'.
    394      'prgN6Qr6ELFQFUWoRpNVjlKwxZB8DCpE+PtfEKqV1cUzxpVudu'.
    395      'GTBHA5Y1g99e+dUio9O/P1Vpq+/WE5GGjDSMoAtAQjrf3C52IP'.
    396      'QxpY4WK2hpReka9Gfrhqgz0bACRoCWjDh56kQ1z9FeuUUQxVhK'.
    397      'B92sD1VahM+bAJgcoJhGjP/6Ln8rAgDiRCVRKiIzxMkkodBJ85'.
    398      'im1IlEHbE4k1xyNveL4YP8HarmGJIOpqyjeQmfNHmTvnqZTWBt'.
    399      'vIJXpPwlukJSuSTKGK3pEwtJmiX00ZlInTyNscImO6XBITvH1c'.
    400      '8vVt2OucdKvIyeKRTNCivsEMgcpg6taYs30nfq0Gqg6hOSSFJ4'.
    401      'BSnJPht0IqEjWmOGocEI6F0J94F0qaL6BntTF0MtUfweKQKAPU'.
    402      'Wwp4OcVnQAmVb0p9DLOzjEhEKnGRmoRc7EzRGlwA6NujAKG4yP'.
    403      '6Sjwc4aVznZ7DK0xXdkDoJf0kGmFBniFBOBGcZSCCSKd0IwN0k'.
    404      'IS+QZWCGVZex4BnUxya3+Zt9iugQbcRFpIAtuHvAZulPUdLhUJ'.
    405      'RqegI3WcqaSXddlT3idsWMSRRGkEtNwmyTifAwyBo7LP+11J0e'.
    406      '7tM7pZOYblHkBLcqZ5LcYtw6Wbd4CM3SpE9foYZsIHoqDKCrbz'.
    407      'mLSQtPwmuhXgtBLs0GBdbXOhFGB7WBKO2F8GXt9/VO97Ya3atF'.
    408      '7nUHnwGjGGQqcPxFEdFqURkEidiZszAERoYIsGju1hq21kWee3'.
    409      'bw15+8WpsvAy3K1+i3JkkhZyPpxxjjPOsfOYiZ+TFhLPzQnHOU'.
    410      'tpzGB2dgA4tscIkKIx19Cxg/fPL7vQJu47eXt1VvsDK8pwPueZ'.
    411      'PuZoQMOqhRoJHSs0kKLBWjvjYinmeQGw1TaX1RFdfZ3LMzYLjA'.
    412      'C++dkn6AaH2Nobk6cxEzdnuG0TdC8zvdJkN0hqkFkO/jwL0fxa'.
    413      'so8sBcuFzQ+/+MRC+BeAHnpwQzn++ee5KT9Eshuy46dcKAXm32'.
    414      '0uzPQhS4GttkH2GQID2Wc0Y4LtAbDxhZ/x5A+e/uTG9+jGceXH'.
    415      '9/ySnnIXnUzOxXe1038mW3ZynNmam4yYWkO+f9cv+Oljz16/lV'.
    416      '9tDz/9nerc1hm8ZEScSRK7VvtYl1i1dklsOKyvc+zg/bzw1O8+'.
    417      '/efkajt56kR1ydlEJBc5H46xzbrJ3dY9wrB7hGcff+6/+279L+'.
    418      '0fHxyiE8XMLl4AAAAASUVORK5CYII=' ;
    419 
    420         //==========================================================
    421         // File: bl_blue.png
    422         //==========================================================
    423         $this->imgdata_large[9][0]= 1169 ;
    424         $this->imgdata_large[9][1]=
    425      'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACEF'.
    426      'BMVEX/////////7//35//v1v/exv/Wvf/Wrf/Wpf/Orf+/v7+9'.
    427      'tc69jP+9hP+5ucW1tc6tlP+rq7Wlpdalpcalpb2cnM6cnMacc/'.
    428      '+cWv+UlLWUjN6UjK2Uc/+Ma/+MUv+EhKWEa/+EQvd7e8Z7e7V7'.
    429      'e6V7c957Wv9za9Zza8ZzSv9ra5xrSv9rOf9rMe9jUudjQv9jOe'.
    430      '9aWpRaUt5aUpRaSu9aSudSUoxSSs5SSoxSMf9KQtZKOfdKMedK'.
    431      'Kf9KKe9CKf9CKb1CKa1CIfdCIedCId45MXs5Kfc5If85Iec5Id'.
    432      'Y5GP8xMbUxMXsxKc4xKZQxIf8xGP8xGO8xGN4xGNYxGL0xGK0p'.
    433      'KXMpIYwpGP8pGO8pGOcpGNYpGM4pEP8pEPcpEOcpEN4pENYpEM'.
    434      'YpEL0hGKUhEP8hEPchEO8hEOchEN4hENYhEM4hEMYhELUhCP8h'.
    435      'CO8hCN4YGJwYGGsYEL0YEK0YEHMYCN4YCM4YCMYYCL0YCKUYAP'.
    436      '8QEJQQEIwQEHsQEGsQCM4QCLUQCK0QCKUQCJwQCJQQCIwQCHMQ'.
    437      'CGsQAP8QAPcQAO8QAOcQAN4QANYQAM4QAMYQAL0QALUQAKUQAJ'.
    438      'QQAIQICGsICGMIAO8IANYIAL0IALUIAK0IAKUIAJwIAJQIAIwI'.
    439      'AIQIAHsIAHMIAGsIAGMAAN4AAMYAAK0AAJQAAIwAAIQAAHMAAG'.
    440      'sAAGMAAFrR1dDlAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
    441      'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFRPMOZ'.
    442      '/2AAAB+klEQVR4nGNgIAIIqeqZmBqpi2JISNml5lVXV3d198Yo'.
    443      'oUjwm1SnxsbGRsSm5ZfNXO4tjCTjVh0ABhFx6QV9E1Y0S8JkuN'.
    444      '3yAgLc7W3t/QPi4jPKJ8ye1yoIlTKpjvVy15eVUbN0i4zKLJ8w'.
    445      'ae6qcKgLqmMj3PUFWFl5NJ0CExLLJzbNW7BWCyxlXR0ba6/Axs'.
    446      'zELmfnkRBT0QiSKgXJCOflxUbYy3KyMHEoOrtEZ1c2TZ6/cMl6'.
    447      'eaCUamdsbIC7tjgPr4SBS3BMMVDTwkXr1hsDpYy6UmMj/O0tdX'.
    448      'QNbDxjknJLWqYsXLx0vStQynxGflpkZGCgs7Onp29SbtNkoMy6'.
    449      'pevCgFJWy3oyMuKjgoKCPWNCvEuqWhcsWrJ06XqQlPnMvrKyrM'.
    450      'TomJjkZAfHlNa2qdOWrlu63gcopbG8v7+hvLwip7g4JdSxsLZu'.
    451      '8dKlS9ettwBKic2eNXHChIkTG5tKqgpr2uo6loLAehWQx0LnzJ'.
    452      '49p6mpeXLLlNq6RUvqly6dvnR9Bx9ISnnlvLmT582bMr9t4aL2'.
    453      '+vrp60GaDCGB6Ld6wfwFCxYCJZYsXQ+SmL6+FBryInVrFi1atH'.
    454      'jJkqVQsH6pNCzCJNvXrQW6CmQJREYFEc2CYevXrwMLAyXXl0oz'.
    455      'IAOt0vVQUGSIkabkDV3DwlzNVDAksAAAfUbNQRCwr88AAAAASU'.
    456      'VORK5CYII=' ;
    457 
    458         //==========================================================
    459         // File: bs_red.png
    460         //==========================================================
    461         $this->imgdata_small[0][0]= 437 ;
    462         $this->imgdata_small[0][1]=
    463      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'.
    464      'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'.
    465      'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'.
    466      'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'.
    467      'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'.
    468      'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
    469      'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGDNEMgOYAAAAm0'.
    470      'lEQVR4nI3Q3RKCIBAFYGZMy9RKzX7MVUAUlQTe/+kS0K49d3wD'.
    471      '7JlFaG+CvIR3FvzPXgpLatxevVVS+Jzv0BDGk/UJwOkQ1ph2g/'.
    472      'Ct5ACX4wNT1o/zzUoJUFUGBiGfVnDTYGJgmrWy8iKEtp0Bpd2d'.
    473      'jLGu56MB7f4JOOfDJAwoNwslk/jOUi+Jts6RVNrC1hkhPy50Ef'.
    474      'u79/ADQMQSGQ8bBywAAAAASUVORK5CYII=' ;
    475 
    476 
    477         //==========================================================
    478         // File: bs_lightblue.png
    479         //==========================================================
    480         $this->imgdata_small[1][0]= 657 ;
    481         $this->imgdata_small[1][1]=
    482      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABVl'.
    483      'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'.
    484      'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'.
    485      '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'.
    486      'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'.
    487      'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'.
    488      'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'.
    489      'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'.
    490      'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'.
    491      'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'.
    492      'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'.
    493      'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGTok'.
    494      '9Yp9AAAAtElEQVR4nGNgIBaw8wkpKghzwvksPAKiUsraprYiLF'.
    495      'ARXkE2JiZ1PXMHXzGIAIekOFBE08TGLTCOCyzCLyvDxsZqZOnk'.
    496      'E56kAhaRV9NQUjW2tPcMjs9wBYsY6Oobmlk7egRGpxZmgkW0zC'.
    497      '2s7Jy9giKT8gohaiQcnVzc/UNjkrMLCyHmcHr7BYREJKTlFxbm'.
    498      'QOxiEIuKTUzJKgQCaZibpdOzQfwCOZibGRi4dcJyw3S4iQ4HAL'.
    499      'qvIlIAMH7YAAAAAElFTkSuQmCC' ;
    500 
    501         //==========================================================
    502         // File: bs_gray.png
    503         //==========================================================
    504         $this->imgdata_small[2][0]= 550 ;
    505         $this->imgdata_small[2][1]=
    506      'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAMAAADH72RtAAABI1'.
    507      'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'.
    508      'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'.
    509      'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'.
    510      'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'.
    511      'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'.
    512      'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'.
    513      '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'.
    514      'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'.
    515      'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIA'.
    516      'AAsSAdLdfvwAAAAHdElNRQfTAwkUGiIctEHoAAAAfElEQVR4nI'.
    517      '2N2xKDIAwF+bZ2kAa8cNFosBD//yvKWGh9dN+yk9kjxH28R7ze'.
    518      'wzBOYSX6CaNB927Z9qZ66KTSNmBM7UU9Hx2c5qjmJaWCaV5j4t'.
    519      'o1ANr40sn5a+x4biElrqHgrXMeac/c1nEpFHG0LSFoo/jO/BeF'.
    520      'lJnFbT58ayUf0BpA8wAAAABJRU5ErkJggg==' ;
    521 
    522         //==========================================================
    523         // File: bs_greenblue.png
    524         //==========================================================
    525         $this->imgdata_small[3][0]= 503 ;
    526         $this->imgdata_small[3][1]=
    527      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAxl'.
    528      'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'.
    529      '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'.
    530      '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'.
    531      'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'.
    532      'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'.
    533      'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'.
    534      'dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfT'.
    535      'AwkUGTIqLgJPAAAAqklEQVR4nI2QVxOCMBCEM6Mi2OiCvSslJB'.
    536      'CUoqjn//9TYgCfubf9Zu9uZxFqO+rscO7b6l/LljMZX29J2pNr'.
    537      'YjmX4ZaIEs2NeiWO19NNacl8rHAyD4LR6jjw6PMRdTjZE0JOiU'.
    538      'dDv2ALTlzRvSdCCfAHGCc7yRPSrAQRQOWxKc3C/IUjBlDdUcM8'.
    539      '97vFGwBY9QsZGBc/A4DWZNbeXIPWZEZI0c2lqSute/gCO9MXGY'.
    540      '4/IOkAAAAASUVORK5CYII=' ;
    541 
    542         //==========================================================
    543         // File: bs_yellow.png
    544         //==========================================================
    545         $this->imgdata_small[4][0]= 507 ;
    546         $this->imgdata_small[4][1]=
    547      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAzF'.
    548      'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'.
    549      'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'.
    550      'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'.
    551      'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'.
    552      'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'.
    553      '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'.
    554      'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAH'.
    555      'dElNRQfTAwkUGSDZl3MHAAAAqElEQVR4nI3QWRNDMBAA4My09E'.
    556      'IF1SME0VT1okXvM/3//6kEfbZv+81eswA0DfHxRpOV+M+zkDGG'.
    557      'rL63zCoJ2ef2RLZDIqNqYexyvFrY9ePkxGWdpvfzC7tEGtIRly'.
    558      'nqzboFKMlizAXbNnZyiFUKAy4bZ+B6W0lRaQDLmg4h/k7eFwDL'.
    559      'OWIky8qhXUBQ7gKGmsxpC+ah1TdriwByqG8GQNDNr6kLjf/wAx'.
    560      'KgEq+FpPbfAAAAAElFTkSuQmCC' ;
    561 
    562         //==========================================================
    563         // File: bs_darkgray.png
    564         //==========================================================
    565         $this->imgdata_small[5][0]= 611 ;
    566         $this->imgdata_small[5][1]=
    567      'iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAABJl'.
    568      'BMVEX////////o8v/f6O7W4OnR3PXL1OTL0evEyLvCzePAwMC/'.
    569      'v7a8wsq7t7C1xum1vtS1q6GzopmyxeKsrsOqvNWoq7anvN+nsb'.
    570      'qhrcGgqbGfpq6cp7+bqMuVmJKRm7yPlKKMnL6FkKWFipOEkLSE'.
    571      'j6qEhoqAiaB+jqd8haF7hZR4iJt4g5l3hZl2gIt2cod1hJVzeY'.
    572      'VzboJvhp9sfJJsb41peY1pd5xpdoVod4xndI5lcHxka4BjcYVg'.
    573      'Z3BfboFbb4lbZnZbYntaZ4laZYVZV3JYYWpXX3JWWm5VX4RVW2'.
    574      'NUYX9SXHxPWn5OVFxNWWtNVXVMVWFKV3xHUGZGU3dGTldFSlxE'.
    575      'Sk9ESXBCRlNBS3k/SGs/RU4+R1k9R2U6RFU2PUg0PEQxNU0ECL'.
    576      'QWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAA'.
    577      'CxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGQmbJetrAAAAtklEQV'.
    578      'R4nGNgwAK4JZTNNOWlYDxhMT4ZDTOzQE1uMF9CiJWVU0LbxDlS'.
    579      'G8QVF+FnZ2KRNHAIiPUHaZGSlmZj5lH19A1KjLUA8lXU5MWllF'.
    580      'yjo30TYr2BfG19G11b37CEeN84H38gX1HbwTUkOjo+zjfG3hLI'.
    581      'l1exCvCNCwnxjfMz0gTyRdXNHXx9fUNCQu2MwU6SN3ZwD42LCH'.
    582      'W30IK4T8vUJSAkNMhDiwPqYiktXWN9JZj7UQAAjWEfhlG+kScA'.
    583      'AAAASUVORK5CYII=' ;
    584 
    585 
    586         //==========================================================
    587         // File: bs_darkgreen.png
    588         //==========================================================
    589         $this->imgdata_small[6][0]= 666 ;
    590         $this->imgdata_small[6][1]=
    591      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABX1'.
    592      'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'.
    593      'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'.
    594      'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'.
    595      'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'.
    596      '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'.
    597      'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'.
    598      'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'.
    599      'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'.
    600      'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'.
    601      'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'.
    602      'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
    603      'RQfTAwkUGRjxlcuZAAAAtElEQVR4nGNgIBZw8osqqIpzw/msfI'.
    604      'IiUmr6lo6SbFARASEOJiYtQ2uXADmIAJeEGFBE18LBMySBBywi'.
    605      'LC/LwcFiZuvmH5WiAxZR0tRW1DC3dfYJS8zyAouYGBibWtm7+o'.
    606      'TEpZfkgEX0rG3snNx9Q2NSCksgaqRd3Ty8gyLiU/NKSiDmcPsF'.
    607      'BodHJ2UUlZTkQ+xikIlNSE7LLgECZagL2VQyc0H8YnV2uD94jS'.
    608      'ILIo14iQ4HALarJBNwbJVNAAAAAElFTkSuQmCC' ;
    609 
    610         //==========================================================
    611         // File: bs_purple.png
    612         //==========================================================
    613         $this->imgdata_small[7][0]= 447 ;
    614         $this->imgdata_small[7][1]=
    615      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAnF'.
    616      'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'.
    617      'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'.
    618      'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'.
    619      'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'.
    620      'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
    621      'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGS'.
    622      'o5QpoZAAAAnElEQVR4nI3Q2xJDMBAG4MyQokWrZz3oSkJISJH3'.
    623      'f7dK0Gv/Xb7J7vyzCK0NjtPsHuH/2wlhTE7LnTNLCO/TFQjjIp'.
    624      'hHAA6bY06LSqppMAY47x+04HXTba2kAFlmQKr+YuVDCGUG2k6/'.
    625      'rNwYK8rKwKCnPxHnVS0aA3rag4UQslUGhrlk0Kpv1+sx3tLZ6w'.
    626      'dtYemMkOsnz8R3V9/hB87DEu2Wos5+AAAAAElFTkSuQmCC' ;
    627 
    628 
    629         //==========================================================
    630         // File: bs_brown.png
    631         //==========================================================
    632         $this->imgdata_small[8][0]= 677 ;
    633         $this->imgdata_small[8][1]=
    634      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABaF'.
    635      'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'.
    636      'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'.
    637      'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'.
    638      'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'.
    639      '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'.
    640      'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'.
    641      'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'.
    642      'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'.
    643      'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'.
    644      'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'.
    645      'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLd'.
    646      'fvwAAAAHdElNRQfTAwkUGho0tvl2AAAAtklEQVR4nGNgIBaoSg'.
    647      'mLKGpowfkGMty8AqJKpi4mRlAROR5ONg4JFUv3YHOIgDo/HwsT'.
    648      'q6yps29EsjZYREFIkJ2ZS9/OMzA20wEsIi8uKSZtaOPmH5WSFw'.
    649      'YW0VRW07Vw8vCLSMguLwCL6FlaObp6B0TGZxSXQ9TouHv6+IXG'.
    650      'JGYWlpdDzNEKCgmPjkvLKS0vL4LYxWAen5SelV8OBNZQFxrZ5h'.
    651      'aC+GX2MDczMBh7pZakehkTHQ4AA0Am/jsB5gkAAAAASUVORK5C'.
    652      'YII=' ;
    653 
    654         //==========================================================
    655         // File: bs_blue.png
    656         //==========================================================
    657         $this->imgdata_small[9][0]= 436 ;
    658         $this->imgdata_small[9][1]=
    659      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'.
    660      'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'.
    661      'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'.
    662      'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'.
    663      'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'.
    664      'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
    665      'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGhNNakHSAAAAmk'.
    666      'lEQVR4nI3P2xKCIBAGYGfM6SBWo1nauIqogaDA+z9dK9Lhrv47'.
    667      'vtl/2A2CfxNlJRRp9IETYGraJeEb7ocLNKznia8A7Db7umWDUG'.
    668      'sxAzhurxRHxok4KQGqCuEhlL45oU1D2w5BztY4KRhj/bCAsetM'.
    669      '2uObjwvY8/oX50JItYDxSyZSTrO2mNhvGMbaWAevnbFIcpuTr7'.
    670      't+5AkyfBIKSJHdSQAAAABJRU5ErkJggg==' ;
    671 
    672         //==========================================================
    673         // File: bs_green.png
    674         //==========================================================
    675         $this->imgdata_small[10][0]= 452 ;
    676         $this->imgdata_small[10][1]=
    677      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAn1'.
    678      'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'.
    679      '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'.
    680      'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'.
    681      '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'.
    682      'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'.
    683      'AIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAw'.
    684      'kUGgW5vvSDAAAAnklEQVR4nI3QSxKCMAwA0M4gqCgoiiJ+kEAL'.
    685      'LQUq0PufzX7ENdnlJZNkgtDS2CYZvK6bf+7EoKLA9cH5SQzv6A'.
    686      'YloTywsAbYr44FrlgrXCMJwHl3xxVtuuFkJAPIcw2tGB9GcFli'.
    687      'oqEf5GTkSUhVMw2TtD0XSlnDOw3SznE5520vNEi7CwW9+Ayjyq'.
    688      'U/3+yPuq5gvhkhL0xlGnqL//AFf14UIh4mkEkAAAAASUVORK5C'.
    689      'YII=' ;
    690 
    691 
    692         //==========================================================
    693         // File: bs_white.png
    694         //==========================================================
    695         $this->imgdata_small[11][0]= 480 ;
    696         $this->imgdata_small[11][1]=
    697      'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAABm'.
    698      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
    699      'B3RJTUUH0wMLFTsY/ewvBQAAAW1JREFUeJytkz2u4jAUhT/jic'.
    700      'gfBUKiZhE0bIKeVbCWrIKenp6eDiGlCEEEBArIxvzGU4xeZjLk'.
    701      'jWb05lRXuvbx+exr4bouX1Xjyw7Atz81F4uFBYjjGIDhcCjq1o'.
    702      'k6nN1uZwFerxfP55Msy1itVmRZBsB4PK6YveHkeW5d18XzPIIg'.
    703      'wPd9Wq0WnU6HMAxJkoQoiuynOIfDwUopkVIihKAoCgAcx6Hdbm'.
    704      'OMIU1T5vN55eBKEikljUYDIX6kFUKU9e8aDAZlmjcca+1b7TgO'.
    705      '1+uVy+VS9nzfr8e53++VzdZaiqIgz3OMMWitOZ/PaK0JgqDeRC'.
    706      'mF53lIKYGfr3O73TDGoJQiTVO01nS73XqT4/FIs9kkCAIej0eZ'.
    707      'brPZEMcxSZKgtQZgMpmIWpN+vy+m06n1PK9yTx8Gy+WS/X5Pr9'.
    708      'er9GuHLYoiG4YhSilOpxPr9Zrtdlti/JriU5MPjUYjq7UuEWaz'.
    709      '2d+P/b/qv/zi75oetJcv7QQXAAAAAElFTkSuQmCC' ;
    710 
    711 
    712         //==========================================================
    713         // File: bs_cyan.png
    714         //==========================================================
    715         $this->imgdata_small[12][0]= 633 ;
    716         $this->imgdata_small[12][1]=
    717      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABPl'.
    718      'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'.
    719      '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'.
    720      'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'.
    721      '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'.
    722      'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'.
    723      '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'.
    724      '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'.
    725      'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'.
    726      'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'.
    727      'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
    728      'AHdElNRQfTAwkUGQDi+VPPAAAAtElEQVR4nGNgIBawikipyIiy'.
    729      'wfksfJpGRkamNtr8LFARPiMFHmFDcztXfwGoFi0jLiZuZRtnry'.
    730      'BddrCIiJEGL6eklYO7X3iCOFhE2thESdHawdUnJDZFDiyiamZh'.
    731      'aevk5h0UlZSpBhaRtbN3dPHwDY5MSM+EqBFzc/f0DgiLTkjLzI'.
    732      'SYw6bjHxgaEZeckZmpD7GLQSAqJj4xNRMIBGFuFtRLA/ENhGBu'.
    733      'ZmDgkJBXl5fgIDocAAKcINaFePT4AAAAAElFTkSuQmCC' ;
    734 
    735         //==========================================================
    736         // File: bs_bluegreen.png
    737         //==========================================================
    738         $this->imgdata_small[13][0]= 493 ;
    739         $this->imgdata_small[13][1]=
    740      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAvV'.
    741      'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'.
    742      'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'.
    743      '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'.
    744      'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'.
    745      '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'.
    746      'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'.
    747      'AJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGxNUcXCT'.
    748      'AAAAqUlEQVR4nI2Q1xKCMBREM2NHLCCogAGCjd6SqLT8/2cZKT'.
    749      '6zb3tm987OBWCsXoejp8rC35fi4+l6gXFZlD0Rz6fZ1tdDmKR9'.
    750      'RdOmkzmP7DDpilfX3SzvRgQ/Vr1uiZplfsCBiVf03RJd140wgj'.
    751      'kmNqMtuYXcxyYmNWJdRoYwzpM9qRvGujuCmSR7q7ARY00/MiWk'.
    752      'sCnjkobNEm1+HknDZgAqR0GKU43+wxdu2hYzbsHU6AAAAABJRU'.
    753      '5ErkJggg==' ;
    754 
    755         //==========================================================
    756         // File: bs_lightred.png
    757         //==========================================================
    758         $this->imgdata_small[14][0]= 532 ;
    759         $this->imgdata_small[14][1]=
    760      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAA3l'.
    761      'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'.
    762      'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'.
    763      'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'.
    764      'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'.
    765      'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'.
    766      'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'.
    767      'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
    768      'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGjoP2Nm+AAAAr0'.
    769      'lEQVR4nGNgIBaYiOk62imYwPnMkiIyso76yhJSzFARMxkRNk49'.
    770      'a3t5OW6oFk1LVkYOfWUHKxUXiEYzLS12DnN3VXkjIRtFsIiSk5'.
    771      '6evqGqhYGKugAfWMRa1FpD2UHeQEXQRlgALCJur+rgbCUNFOAS'.
    772      'hqjRkZe3MpBTcwEKCEPMMTGSs3Xz8OQHCnBBHckt6OJpIyAMBD'.
    773      'wwN/MYc4H4LK4wNzMwmGrzcvFqmxIdDgDiHRT6VVQkrAAAAABJ'.
    774      'RU5ErkJggg==' ;
    775 
    776         //==========================================================
    777         // File: bxs_lightred.png
    778         //==========================================================
    779         $this->imgdata_xsmall[0][0]= 432 ;
    780         $this->imgdata_xsmall[0][1]=
    781      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAA3l'.
    782      'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'.
    783      'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'.
    784      'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'.
    785      'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'.
    786      'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'.
    787      'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'.
    788      'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
    789      'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKBOgGhWjAAAAS0'.
    790      'lEQVR4nGNgQAEmunYmEJaMCKe1vBxYzJKVQ9lKBSSupKdnaKGi'.
    791      'zgdkiqs6WKnYcIGYJnK2HvzCwmCNgi42wsLCECNMeXlNUY0HAL'.
    792      'DaB7Du8MiEAAAAAElFTkSuQmCC' ;
    793 
    794         //==========================================================
    795         // File: bxs_bluegreen.png
    796         //==========================================================
    797         $this->imgdata_xsmall[1][0]= 397 ;
    798         $this->imgdata_xsmall[1][1]=
    799      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAvV'.
    800      'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'.
    801      'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'.
    802      '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'.
    803      'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'.
    804      '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'.
    805      'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'.
    806      'AJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKDVyF5Be'.
    807      'AAAASUlEQVR4nGNgQAFmYqJcEJaEOJ+UrD5YTJKFTZrfGCQuaq'.
    808      'glLWvMaQ5kqujo6hnbKIKYXPr68gp2dmCNJiZAlh3ECGsREWtU'.
    809      '4wF1kwdpAHfnSwAAAABJRU5ErkJggg==' ;
    810 
    811         //==========================================================
    812         // File: bxs_navy.png
    813         //==========================================================
    814         $this->imgdata_xsmall[2][0]= 353 ;
    815         $this->imgdata_xsmall[2][1]=
    816      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'.
    817      'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'.
    818      'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'.
    819      'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'.
    820      'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'.
    821      'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
    822      'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJxXO4axZAAAAR0'.
    823      'lEQVR4nGNgQAGskhKsEJaslIi8ijpYTJaDU1FVAyQuKSujoKKh'.
    824      'LQ5kSigpqWro6oOYrOoaWroGBmCNWiCWAdQwUVFWVOMBOp4GCJ'.
    825      's5S60AAAAASUVORK5CYII=' ;
    826 
    827         //==========================================================
    828         // File: bxs_gray.png
    829         //==========================================================
    830         $this->imgdata_xsmall[3][0]= 492 ;
    831         $this->imgdata_xsmall[3][1]=
    832      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABI1'.
    833      'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'.
    834      'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'.
    835      'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'.
    836      'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'.
    837      'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'.
    838      'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'.
    839      '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'.
    840      'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'.
    841      'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEA'.
    842      'AAsRAX9kX5EAAAAHdElNRQfTAwkUKC74clmyAAAAQklEQVR4nG'.
    843      'NgQAVBYVCGt5dXYEQ0mOnp5h4QFgVmeri6+4dHxYMVeHoFRUTH'.
    844      'gTUFBIZBWAwMkZEx8bFQM2Lj0UwHANc/DV6yq/BiAAAAAElFTk'.
    845      'SuQmCC' ;
    846 
    847         //==========================================================
    848         // File: bxs_graypurple.png
    849         //==========================================================
    850         $this->imgdata_xsmall[4][0]= 542 ;
    851         $this->imgdata_xsmall[4][1]=
    852      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABSl'.
    853      'BMVEX////////11P/MqdvKrNfAwMC+u7+9u7+4rr24lsi3rby3'.
    854      'lMe1rLq1o720q7i0oL20ksSzoryyqbaykMGxlb2wkL+vnbiujb'.
    855      '2sjLuri7qpl7GoirWoibenmK2mla6mjLKmhrSllauki7CjhrCj'.
    856      'hLGihLChg6+ggq2fkqadkKOcfqqai6Gag6WYe6WXeqSWeaOTd6'.
    857      'CTd5+Rdp6RdZ6RdZ2Qg5eOc5qMcpiLcZeJb5WIbpOHbZKGbJGE'.
    858      'a4+CaY2AZ4t/Z4p/Zop/Zol+Zol7ZIZ6Y4V5YoR1ZH11X391Xn'.
    859      '9zXX1yXXtxXHtvWnluWXhsV3VqVnNpVXJoVHFnU3BmUm9jUGth'.
    860      'VGdgTmheTGZcS2RcSmRaSWJYR19XRl5SQllRQlhQQVdPQFZOP1'.
    861      'VLPlFJO09IPE5IOk5FOEtEN0lDOEpDOElDNklCNkc/M0XhbrfD'.
    862      'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
    863      'EAAAsRAX9kX5EAAAAHdElNRQfTAwkUKCgREfyHAAAATUlEQVR4'.
    864      'nGNgQAEcIko8EBY3M5Ougy+IxSXMwmTsFsAHZMqrSRvZB0W7A5'.
    865      'k6FlYugXEZICaPr394Um4uSAFDRFRCbm4uxAihsDAhVOMBHT0L'.
    866      'hkeRpo8AAAAASUVORK5CYII=' ;
    867 
    868         //==========================================================
    869         // File: bxs_red.png
    870         //==========================================================
    871         $this->imgdata_xsmall[5][0]= 357 ;
    872         $this->imgdata_xsmall[5][1]=
    873      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'.
    874      'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'.
    875      'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'.
    876      'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'.
    877      'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'.
    878      'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
    879      'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIyjy5SVMAAAAS0'.
    880      'lEQVR4nGNgQAFsUpJsEJastIi8ijpYTJaDU0FVgxXIlJKVUVDR'.
    881      '0BYHMiUUlVQ1dPVBTDZ1dS1dAwOQAgYtbSDLAGIEq6goK6rxAD'.
    882      'yXBg73lwGUAAAAAElFTkSuQmCC' ;
    883 
    884         //==========================================================
    885         // File: bxs_yellow.png
    886         //==========================================================
    887         $this->imgdata_xsmall[6][0]= 414 ;
    888         $this->imgdata_xsmall[6][1]=
    889      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAzF'.
    890      'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'.
    891      'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'.
    892      'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'.
    893      'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'.
    894      'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'.
    895      '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'.
    896      'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAH'.
    897      'dElNRQfTAwkUIzoBXFQEAAAAS0lEQVR4nGNgQAFsDhJsEJaTo5'.
    898      '2skj5YzMnSSk7ZwBzIlOSUklPiMxYHMnW4FXT5VNVBTDZeXiNV'.
    899      'QUGQAgYBYyBLEGIEq5gYK6rxAH4kBmHBaMQQAAAAAElFTkSuQm'.
    900      'CC' ;
    901 
    902         //==========================================================
    903         // File: bxs_greenblue.png
    904         //==========================================================
    905         $this->imgdata_xsmall[7][0]= 410 ;
    906         $this->imgdata_xsmall[7][1]=
    907      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAxl'.
    908      'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'.
    909      '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'.
    910      '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'.
    911      'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'.
    912      'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'.
    913      'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'.
    914      'dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfT'.
    915      'AwkUJy5/6kV9AAAATUlEQVR4nGNgQAGCyuyCEJaGugKHviVYzF'.
    916      'hO3sxCWwDIVNLTM9PXtpEGMhW12Cy0DR1ATEFLSxZ7BweQAgYd'.
    917      'HUMHBweIEQKiogKoxgMAo/4H5AfSehsAAAAASUVORK5CYII=' ;
    918 
    919         //==========================================================
    920         // File: bxs_purple.png
    921         //==========================================================
    922         $this->imgdata_xsmall[8][0]= 364 ;
    923         $this->imgdata_xsmall[8][1]=
    924      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAnF'.
    925      'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'.
    926      'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'.
    927      'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'.
    928      'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'.
    929      'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
    930      'HUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIj'.
    931      'mBTjT/AAAASUlEQVR4nGNgQAGskhKsEJaCrJiSuhZYTEFASFlD'.
    932      'GyQuqSCnrK6tJwpkiquoamgbGIGYrFpaugbGxmCNunpAljHECB'.
    933      'ZBQRZU4wFSMAZsXeM71AAAAABJRU5ErkJggg==' ;
    934 
    935         //==========================================================
    936         // File: bxs_green.png
    937         //==========================================================
    938         $this->imgdata_xsmall[9][0]= 370 ;
    939         $this->imgdata_xsmall[9][1]=
    940      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAn1'.
    941      'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'.
    942      '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'.
    943      'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'.
    944      '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'.
    945      'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'.
    946      'AIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAw'.
    947      'kUKBrZxq0HAAAATElEQVR4nGNgQAGccrIcEJaivISyhjaIxa7I'.
    948      'I6CiqcMKZMopKqho6OhLA5kyqmqaOobGICartraeoYkJSAGDnj'.
    949      '6QZQIxgk1Skg3VeABlVgbItqEBUwAAAABJRU5ErkJggg==' ;
    950 
    951         //==========================================================
    952         // File: bxs_darkgreen.png
    953         //==========================================================
    954         $this->imgdata_xsmall[10][0]= 563 ;
    955         $this->imgdata_xsmall[10][1]=
    956      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABX1'.
    957      'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'.
    958      'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'.
    959      'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'.
    960      'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'.
    961      '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'.
    962      'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'.
    963      'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'.
    964      'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'.
    965      'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'.
    966      'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'.
    967      'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'.
    968      'RQfTAwkUKCFozUQjAAAATUlEQVR4nGNgQAGcoqrcEJYQB5OhSw'.
    969      'CIxSXGwWThGcIDZCppK5o7hyV6AZl6NnbuoSmFICZ3YHB0RkkJ'.
    970      'SAFDbEJaSUkJxAjeyEheVOMBQj4MOEkWew4AAAAASUVORK5CYI'.
    971      'I=' ;
    972 
    973         //==========================================================
    974         // File: bxs_cyan.png
    975         //==========================================================
    976         $this->imgdata_xsmall[11][0]= 530 ;
    977         $this->imgdata_xsmall[11][1]=
    978      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABPl'.
    979      'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'.
    980      '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'.
    981      'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'.
    982      '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'.
    983      'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'.
    984      '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'.
    985      '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'.
    986      'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'.
    987      'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'.
    988      'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAA'.
    989      'AHdElNRQfTAwkUKQFKuFWqAAAATUlEQVR4nGNgQAGsUjJsEJaR'.
    990      'grC5qz9YzIiL28YriB3IlDZRsnYNiZUDMmXtHT2CE9JBTDb/wI'.
    991      'jkzEyQAoaomMTMzEyIERzy8hyoxgMAN2MLVPW0f4gAAAAASUVO'.
    992      'RK5CYII=' ;
    993 
    994         //==========================================================
    995         // File: bxs_orange.png
    996         //==========================================================
    997         $this->imgdata_xsmall[12][0]= 572 ;
    998         $this->imgdata_xsmall[12][1]=
    999      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABaF'.
    1000      'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'.
    1001      'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'.
    1002      'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'.
    1003      'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'.
    1004      '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'.
    1005      'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'.
    1006      'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'.
    1007      'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'.
    1008      'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'.
    1009      'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'.
    1010      'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9k'.
    1011      'X5EAAAAHdElNRQfTAwkUJBSSy88MAAAATUlEQVR4nGNgQAGqwo'.
    1012      'paEBYPJ4eKezCIpc7HwmrqG6ENZMpLihm6RaWEAZl6Vo7ekRnF'.
    1013      'IKZWSHhcTnk5SAFDfFJWeXk5xAjj1FRjVOMBeFwNcWYSLjsAAA'.
    1014      'AASUVORK5CYII=' ;
    1015 
    1016         //==========================================================
    1017         // File: bxs_lightblue.png
    1018         //==========================================================
    1019         $this->imgdata_xsmall[13][0]= 554 ;
    1020         $this->imgdata_xsmall[13][1]=
    1021      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABVl'.
    1022      'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'.
    1023      'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'.
    1024      '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'.
    1025      'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'.
    1026      'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'.
    1027      'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'.
    1028      'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'.
    1029      'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'.
    1030      'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'.
    1031      'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'.
    1032      'gAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJziL'.
    1033      'PvAsAAAATUlEQVR4nGNgQAHsQgqcEJYgG5Oegy+IxSHOxmTiFs'.
    1034      'gFZMprKBnbB8e7AplaFlbOQUl5ICanX0BEWmEhSAFDVGxKYWEh'.
    1035      'xAjusDBuVOMBJO8LrFHRAykAAAAASUVORK5CYII=' ;
    1036 
    1037         //==========================================================
    1038         // File: bxs_darkgray.png
    1039         //==========================================================
    1040         $this->imgdata_xsmall[14][0]= 574 ;
    1041         $this->imgdata_xsmall[14][1]=
    1042      'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABm'.
    1043      'JLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAB'.
    1044      'iElEQVR42k3QPU8TYRwA8P//ebkXrgdIColXRAOEkJqbaExMut'.
    1045      'DBhE1GNjYHPg+DG6ODiU6QOLjVxITBcFKBYCstlAC2Bz17fe76'.
    1046      'vLD6+wg/1FpTRFR5lpaub/u1eGBGaAT4HneD4OlXx7avtDYUjT'.
    1047      'HQabd2Ti8e3vVSKzxrtHS32wIpFVldno22Nqvvg2Bhl0gp/aNm'.
    1048      'vJ3qqXAtLIva+ks1H0wqlSXi4+d6+OFTfRsAfHJx2d1od24rZP'.
    1049      'xP2HzopINr1mkesX7ccojqif0v9crxWXODZTno3+dNGA7uWLsd'.
    1050      'mUYU4fHJCViMG9umLBmM4L6fagZGg9QKfjZ+Qfy3C3G/B3mugF'.
    1051      'IHHNcDf64E3KJALApk2p8CSolUUqLjFkyxOGMsTtFyJ+Wz57NQ'.
    1052      '8DghS4sLB0svioeZZo7nPhFoUKZDIVFbglkTTnl5/rC8snjAkJ'.
    1053      'Bk/XV5LxHC/v7tR8jzTFPbg8LENK9WX0Vv31T2AEmCSmlKCCoh'.
    1054      'ROnP1U1tPFYjJBRcbtzSf+GPsFTAQBq1n4AAAABKdEVYdHNpZ2'.
    1055      '5hdHVyZQBiYzYyMDIyNjgwYThjODMyMmUxNjk0NWUzZjljOGFh'.
    1056      'N2VmZWFhMjA4OTE2ZjkwOTdhZWE1MzYyMjk0MWRkM2I5EqaPDA'.
    1057      'AAAABJRU5ErkJggg==' ;
     73    function ImgData_Balls() {
     74
     75//==========================================================
     76// File: bl_red.png
     77//==========================================================
     78        $this->imgdata_large[0][0]= 1072 ;
     79        $this->imgdata_large[0][1]=
     80            'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAByF'.
     81            'BMVEX/////////xsb/vb3/lIz/hIT/e3v/c3P/c2v/a2v/Y2P/'.
     82            'UlL/Skr/SkL/Qjn/MTH/MSn/KSn/ISH/IRj/GBj/GBD/EBD/EA'.
     83            'j/CAj/CAD/AAD3QkL3MTH3KSn3KSH3GBj3EBD3CAj3AAD1zMzv'.
     84            'QkLvISHvIRjvGBjvEBDvEAjvAADnUlLnSkrnMTnnKSnnIRjnGB'.
     85            'DnEBDnCAjnAADec3PeSkreISHeGBjeGBDeEAjWhITWa2vWUlLW'.
     86            'SkrWISnWGBjWEBDWEAjWCAjWAADOnp7Oa2vOGCHOGBjOGBDOEB'.
     87            'DOCAjOAADJrq7Gt7fGGBjGEBDGCAjGAADEpKS/v7+9QkK9GBC9'.
     88            'EBC9CAi9AAC1e3u1a2u1Skq1KSm1EBC1CAi1AACtEBCtCBCtCA'.
     89            'itAACngYGlCAilAACghIScOTmcCAicAACYgYGUGAiUCAiUAAiU'.
     90            'AACMKSmMEACMAACEa2uEGAiEAAB7GBh7CAB7AABzOTlzGBBzCA'.
     91            'BzAABrSkprOTlrGBhrAABjOTljAABaQkJaOTlaCABaAABSKSlS'.
     92            'GBhSAABKKSlKGBhKAABCGBhCCABCAAA5CAA5AAAxCAAxAAApCA'.
     93            'ApAAAhAAAYAACc9eRyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
     94            'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFD'.
     95            'UHLytKAAAB4UlEQVR4nGNgIAK4mGjrmNq6BmFIWMmISUpKSmk5'.
     96            'B8ZEokj4qoiLiQCBgqald3xaBpKMj6y4sLCQkJCIvIaFV0RaUR'.
     97            'lCSk5cWEiAn19ASN7QwisuraihHiajKyEixM/NwckjoKrvEACU'.
     98            'qumpg7pAUlREiJdNmZmLT9/cMzwps7Smc3I2WEpGUkxYkJuFiY'.
     99            'lTxszePzY1v7Shc2oX2D+K4iLCgjzsrOw8embuYUmZeTVtPVOn'.
     100            'gqSslYAOF+Ln4ZHWtXMPTcjMrWno7J82rRgoZWOsqaCgrqaqqm'.
     101            'fn5peQmlsK1DR52vRaoFSIs5GRoYG5ub27n19CYm5pdVPnxKnT'.
     102            'pjWDpLydnZwcHTz8QxMSEnJLgDL9U6dNnQ6Sio4PDAgICA+PTU'.
     103            'zNzSkph8hADIxKS46Pj0tKTc3MLSksqWrtmQySAjuDIT8rKy0r'.
     104            'Kz+vtLSmur6jb9JUIJgGdjxDQUVRUVFpaUVNQ1NrZ9+kKVOmTZ'.
     105            'k6vR0sldJUAwQNTU2dnX0TgOJTQLrSIYFY2dPW1NbW2TNxwtQp'.
     106            'U6ZMmjJt2rRGWNB3TO7vnzh5MsgSoB6gy7sREdY7bRrQEDAGOb'.
     107            'wXOQW0TJsOEpwClmxBTTbZ7UDVIPkp7dkYaYqhuLa5trYYUxwL'.
     108            'AADzm6uekAAcXAAAAABJRU5ErkJggg==' ;
     109
     110//==========================================================
     111// File: bl_bluegreen.png
     112//==========================================================
     113        $this->imgdata_large[1][0]= 1368 ;
     114        $this->imgdata_large[1][1]=
     115            'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'.
     116            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
     117            'B3RJTUUH0wMMFi8hE9b2uAAABOVJREFUeNq9lk2sJFUVx3+3qv'.
     118            'tW95t57zFvhiFxmCFRUJRoNCQiJARMhiFx/Igxii5goTG6ZDAu'.
     119            '/EhcSCIrTAgLEiKsJ8ywABNZEMJXEDYCukAmjgjzBkK/j35V1d'.
     120            '333FtV97io97pfzwxfG86qcu/N+Z3zP+fcW/Apmfk4hx57+R/6'.
     121            'Rqmc9ykhsWjlsUngAA1fXIQ7b73pI/186IGHnn9dH/8frC8v4I'.
     122            'PiG53uaerR4GmKkv31mB8cyfjd946ZTwR66qVX9OTWIi8UKUv9'.
     123            'BOrZXpYZvFeiBvzI0fgSUSFKwbVG+Pl1V3HH0VvNR4KeeukV/f'.
     124            'PmMmdHhst76aXD64AbeVQ9bjNHaiGOC2o3wLrAb2/4LL/84ffn'.
     125            'fCdzkOdayKpLppBemrBsU5Y1Zdmm9LJdGU6E/t4M24Q26jRDRL'.
     126            'j3mdc49cSTekFsMzs5XuTsyLDUNSDQ25NwKOly9YIl22MYhJr/'.
     127            'uoDtBBoT0CxBRGYOAhibIaOCe//2MpfM6KHnX9cXipSlbkKWmS'.
     128            'nk9iv38J0jixw7vJfrTMYBOvhSoQHJBS09ANELloAGDxW8tfoW'.
     129            'J+5/UC8CPS0LU7r3SpYarr7M8rmFjMPLXT6/33L4si7Z2GCrQC'.
     130            '+0ctlOaNs9DReV8vSLr85ndPLpZ/WNvHW+01kAVFBOGvJx0wYg'.
     131            'Sp47RIQ4Emwa8FGJXlDxSCFo5YlVgAo2hwPue/hRndboTV3EW2'.
     132            'Wp3k6wBp8q56QiWzecW6vwQfnPRkAWhFgILnq08jQ+R2nlUzzN'.
     133            'uES9Q7Vd+9fba7NmWJW61db2247qACmcjxXr45psYphsFGSLBu'.
     134            'kIajxqtjNwHkvAjQt0sg3crhPA2+fPz0CuyNFOghsGsr19mnFg'.
     135            'DGwrRm8UoAtNmQPQtRXDgdC4HImCFEKcCE0oieUWUYq2LtbiGp'.
     136            'mBQmppfIkjw45DK0QNNkvQ0jMBtPL0UnDRM1rN+cxKwzvOo2NP'.
     137            'tykR9a1kfpZNDLMG6QDYJqCTBvUe1+uxs+YKyPoGrTwY2HhvC4'.
     138            'CDWQd5d4xNApNQEEMgjgLdUCLBQ5cprL/trwNwKG2IUmDqDFd5'.
     139            'sr5BWrlxuSdLDFEFlqAzXGc4zFjupqh6uqYihpxJcEgp026l2w'.
     140            '7wFUv7Z6AvrfRo/n0OYzPwIKE3HUKAJg2otMBiElnsF7wngis9'.
     141            '3ZDjNnLi7huCWUZfueZKTu/M0V3HvmkOFDVxVKDG04ScejSgW5'.
     142            'V0q5JYFEghuDLHlTmToqDeGOCKIVtrW9hsdmXufEcNLPSXuPHa'.
     143            'a+bvuh9df5AH/v5PDFmbWQC3Mx+TVvfGVTRB2CodNgT2JBX003'.
     144            'aANZAYS/BxCv32TV/l2C03G7jgmfjGiT/qmeEmibEYm7XzAO2k'.
     145            'A+pbgHhBgydqu54YO5eRiLCy7yDvPP6Xqf+5Z+Lu277OYuOpiw'.
     146            'H15oBmlNOMcmK5RbP+PrEscGU+DSAxdg4CICIkxnLP8aNz63Og'.
     147            'H3/rdvOb795GVhuaYo0oBc3GGrEsUPVTwO6a7LYd+X51x3Hu/t'.
     148            'lP5tS65FN+6okn9U+n/sqb596dTvhOF+02myXTmkQNrOw7yD3H'.
     149            'j14E+UDQjp24/0E9/eKrbA4HH3aMK1b2ccvXvswjv//1J/s5ud'.
     150            'Due/hRPfP+OmfOrk7vrn7a48ihA3zh8CH+8Iuffiw/n4r9H1ZZ'.
     151            '0zz7G56hAAAAAElFTkSuQmCC' ;
     152
     153//==========================================================
     154// File: bl_yellow.png
     155//==========================================================
     156        $this->imgdata_large[2][0]= 1101 ;
     157        $this->imgdata_large[2][1]=
     158            'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'.
     159            'BMVEX//////////+///+f//9b//8b//73//7X//63//6X//5T/'.
     160            '/4z//4T//3P//2v//1r//0r//0L//zH//yn//yH//xj//xD//w'.
     161            'j//wD/90L/9zn/9zH/9xj/9xD/9wj/9wD39yn37zn37zH37yH3'.
     162            '7xD37wj37wDv70Lv50rv50Lv5znv5yHv5xjv5wjv5wDn51Ln5x'.
     163            'Dn3jHn3iHn3hjn3hDn3gje3oze3nPe3lLe1oze1nPe1lLe1ine'.
     164            '1iHe1hje1hDe1gje1gDW1qXW1mvWzqXWzkLWzhjWzhDWzgjWzg'.
     165            'DOzrXOzq3OzpzOzgDOxkrOxinOxhjOxhDOxgjOxgDGxqXGxnvG'.
     166            'xmvGvRjGvRDGvQjGvQDFxbnAvr6/v7+9vaW9vZS9vQi9vQC9tR'.
     167            'C9tQi9tQC7u7W1tZS1tXu1tTG1tQi1rRC1rQi1rQCtrYytrSGt'.
     168            'rQitrQCtpYStpSGtpQitpQClpYSlpXulpQClnBClnAilnACcnG'.
     169            'ucnAicnACclAiclACUlFqUlCmUlAiUlACUjFKUjAiUjACMjFKM'.
     170            'jEqMjACMhACEhACEewB7ezF7exB7ewB7cwBzcylzcwBzaxBzaw'.
     171            'BraxhrawhrawBrYxBrYwBjYwBjWgBaWgBaUgCXBwRMAAAAAXRS'.
     172            'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'.
     173            'LdfvwAAAAHdElNRQfTAwkRFBKiJZ4hAAAB7ElEQVR4nI3S+1vS'.
     174            'UBgHcB67WJmIMWAVdDHEDLBC6Go0slj3Ft0m9RRBWQEmFZFDEM'.
     175            'Qgt0EMFBY7p/+198hj1kM/9N1+++x73rOd6XT/kStnTx4fPzd9'.
     176            'uwfOjFhomj7smAhwj/6Cm2O0xUwy6g7cCL99uCW3jtBmE7lsdr'.
     177            'fvejgpzP7uEDFRRoqy2k8xQPnypo2BUMP6waF9Vpf3ciiSzErL'.
     178            'XTkPc0zDe3bsHDAcc00yoVgqL3UWN2iENpspff+2vn6D0+NnZ9'.
     179            '6lC5K6RuSqBTZn1O/a3rd7v/MSez+WyIpVFX8GuuCA9SjD4N6B'.
     180            'oRNTfo5PCAVR0fBXoIuOQzab1XjwwNHx00GOj8/nKtV1DdeArk'.
     181            '24R+0ul9PjmbrHPYl+EipyU0OoQSjg8/m83kl/MMhx0fjCkqio'.
     182            'SMOE7t4JMAzDsizH81AqSdW2hroLPg4/CEF4PhKNx98vlevrbY'.
     183            'QQXgV6kXwVfjkTiSXmhYVcSa7DIE1DOENe7GM6lUym0l+EXKks'.
     184            'K20VAeH2M0JvVgrZfL5Qqkiy0lRVaMBd7H7EZUmsiJJcrTdVja'.
     185            'wGpdbTLj3/3qwrUOjAfGgg4LnNA5tdQx14Hm00QFBm65hfNzAm'.
     186            '+yIFhFtzuj+z2MI/MQn6Uez5pz4Ua41G7VumB/6RX4zMr1TKBr'.
     187            'SXAAAAAElFTkSuQmCC' ;
     188
     189//==========================================================
     190// File: bl_silver.png
     191//==========================================================
     192        $this->imgdata_large[3][0]= 1481 ;
     193        $this->imgdata_large[3][1]=
     194            'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAMAAAAM7l6QAAADAF'.
     195            'BMVEUAAADOzs7Gxsa9vb21tbXOxsbOzsbGzsb3///O1ta1vb2c'.
     196            'paVSWlpKWlpSY2ve5+97hIze7/9aY2vO5/9zhJRaa3tSY3PGzt'.
     197            'aMlJxrc3tja3NKUlpCSlK1vcZze4RSWmPW5/+Upb3G3v9zhJxS'.
     198            'Y3t7jKVaa4TO3veltc6ElK1re5Rjc4ycpbV7hJRaY3M5QlLn7/'.
     199            '/Gzt6lrb2EjJzO3v9ja3vG1ve9zu+1xueltdacrc6UpcaMnL1C'.
     200            'SlqElLV7jK1zhKVre5zW3u/O1ue1vc6ttcaMlKVze4xrc4RSWm'.
     201            'tKUmPG1v+9zve1xu+tveeltd6crdbe5/+9xt6cpb17hJxaY3s5'.
     202            'QlrW3vfO1u/Gzue1vdattc6lrcaUnLWMlK2EjKVze5Rrc4xja4'.
     203            'RSWnNKUmtCSmO9xuecpcZ7hKVaY4TW3v/O1vfGzu+1vd6ttdal'.
     204            'rc69xu+UnL2MlLWEjK1ze5xrc5R7hK1ja4zO1v+1veettd6lrd'.
     205            'aMlL3Gzv/39//W1t7Gxs61tb29vcatrbWlpa2cnKWUlJyEhIx7'.
     206            'e4TW1ufGxta1tcZSUlqcnK3W1u+UlKW9vda1tc57e4ytrcalpb'.
     207            '1ra3vOzu9jY3OUlK29vd6MjKWEhJxaWmtSUmNzc4xKSlpjY3tK'.
     208            'SmNCQlqUjJzOxs7///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
     209            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
     210            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
     211            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
     212            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
     213            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
     214            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
     215            'AAAAAAAAAAAAAAAAAAAAAAAAD///9fnkWVAAAAAnRSTlP/AOW3'.
     216            'MEoAAAABYktHRP+lB/LFAAAACXBIWXMAAABFAAAARQBP+QatAA'.
     217            'AB/klEQVR42mNgxAsYqCdd3+lcb4hLmj8wMMvEu8DCMqYbU9op'.
     218            'UEFB2MTb26eyysomFl06XEEhUCHLpAKo2z/fujikEUVaXUFBMB'.
     219            'BouLePuV+VVWGRciIXknSEsImCQd3//xwmPr65llaFcSFJHkjS'.
     220            '3iYmWUDZ//8NfCr989NjNUMSUyTg0jneSiaCINn/gmlVQM12qg'.
     221            'lJnp5waTMTE5NAkCyHWZW/lXWNfUlikmdYK0zax7siS4EDKJtd'.
     222            'mQeU1XRwLBdLkRGASucWmGVnZ4dnhZvn5lmm29iVOWpnJqcuko'.
     223            'JKR1Wm5eTkRKYF5eblp9sU2ZeUJiV7zbfVg0pH56UFBQXNjIqK'.
     224            'jgkujItX1koKTVmYajsdKu2qETVhwgSXiUDZ2Bn9xqUeoZ5e0t'.
     225            'LzYYZ3B092ndjtOnmKTmycW1s7SHa+l5dtB8zlccE6RlN0dGbM'.
     226            'mDVbd5KupNBcL6+F82XgHouLj5vRP2PWLGNdd4+ppnxe8tJec6'.
     227            'XnNsKkm0uVQ5RDRHQTPTym68nPlZbvkfYCexsa5rpJ2qXa5Umm'.
     228            'ocmec3m8vHjmSs+fgxyhC5JDQ8WSPT2lvbzm8vDIe0nbtiBLN8'.
     229            '8BigNdu1B6Lsje+fPbUFMLi5TMfGmvHi/puUAv23q2YCTFNqH5'.
     230            'MvPnSwPh3HasCbm3XUpv+nS5VtrkEkwAANSTpGHdye9PAAAASn'.
     231            'RFWHRzaWduYXR1cmUANGJkODkyYmE4MWZhNTk4MTIyNDJjNjUx'.
     232            'NzZhY2UxMDAzOGFhZjdhZWIyNzliNTM2ZGFmZDlkM2RiNDU3Zm'.
     233            'NlNT9CliMAAAAASUVORK5CYII=' ;
     234
     235//==========================================================
     236// File: bl_purple.png
     237//==========================================================
     238        $this->imgdata_large[4][0]= 1149 ;
     239        $this->imgdata_large[4][1]=
     240            'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACAV'.
     241            'BMVEX/////////7///5///1v//xv//rf//pf//lP//jP//hP//'.
     242            'c///a///Wv//Wvf/Uv//Sv//Qv//Qvf/Off/Mf//Kf//If//If'.
     243            'f/GP//GPf/EP//EPf/CP//CPf/CO//AP//APf3Oe/3Kff3Ke/3'.
     244            'Ie/3GO/3EO/3AO/vSu/vSufvOefvMefvIefvGOfvEOfvCOfvAO'.
     245            'fnUufnSufnMd7nId7nGN7nGNbnEN7nCN7nAN7ejN7ejNbec97e'.
     246            'c9beUtbeQtbeIdbeGNbeENbeCNbeANbWpdbWa9bWQs7WGM7WEM'.
     247            '7WCM7WAM7Otc7Orc7OnM7OSsbOIb3OGMbOEMbOCMbOAM7OAMbG'.
     248            'pcbGnMbGe8bGa8bGKbXGEL3GCL3GAL3FucXBu73AvsC/v7+9pb'.
     249            '29Ka29GLW9ELW9CLW9AL29ALW5rrm1lLW1e7W1MbW1GKW1EK21'.
     250            'CLW1CK21AK2tjK2thKWtMaWtIaWtGJytCK2tCKWtAK2tAKWlhK'.
     251            'Wle6WlEJylCJylAKWlAJyca5ycGJScEJScCJScAJycAJSUWpSU'.
     252            'UoyUKZSUEIyUCIyUAJSUAIyMUoyMSoyMIYSMEISMCISMAIyMAI'.
     253            'SECHuEAISEAHt7MXt7EHt7CHt7AHt7AHNzKXNzEGtzAHNzAGtr'.
     254            'GGtrEGNrCGtrAGtrAGNjCFpjAGNjAFpaAFpaAFIpZn4bAAAAAX'.
     255            'RSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsS'.
     256            'AdLdfvwAAAAHdElNRQfTAwkRFB0ymoOwAAAB9UlEQVR4nGNgIA'.
     257            'K42hhqGtm5+WFIWClKycvLK6gbuARGoEj4aMjLSElISUir6Tt7'.
     258            'x+aEIWR8leQlwEBSTc/CK7awLguuR0lGQkJMVFRUTFJVzwko1d'.
     259            'oFk9OQl5IQE+Dh5hVR0TV3CkkvbJgyASJjDZIR5GBl5eRX0TH1'.
     260            'DEqrbJ2ypBEspSgvJSXKw8bMxMavbOLoGZNf1TZlybw4oIyfLN'.
     261            'BxotxsLEzsQiaOHkFpBQ2905esrAZK2SpIAaUEuDm5+LTNPAKj'.
     262            'C+pbps1evrIDKGWnLictKSkuLKyoZQyUya9o7Z2+YMXKGUApew'.
     263            'M9PTVdXR0TEwf3wOjUirruafOXL18xFyjl72Kpb25qaurg4REU'.
     264            'EFVe2zJ5zpLlK1aCpbydnZ2dnDwDA6NTopLLeiZNXbB8BcTAyP'.
     265            'TQ0JDg4KCY1NS83JKmiVOBepYvX9UPlAovzEiPSU/LLyior2vq'.
     266            'mjZr3vLlIF01IC+XVhUWFlZW1Lc290ycOGfxohVATSsXx4Oksn'.
     267            'vaWlsb2tq6J0+bM2/RohVA81asbIcEYueU3t7JU6ZNnwNyGkhm'.
     268            '+cp5CRCppJnzZ8+ZM3/JUogECBbBIixr8Yqly8FCy8F6ltUgoj'.
     269            'lz7sqVK2ByK+cVMSCDxoUrwWDVysXt8WhJKqG4Y8bcuTP6qrGk'.
     270            'QwwAABiMu7T4HMi4AAAAAElFTkSuQmCC' ;
     271
     272//==========================================================
     273// File: bl_gray.png
     274//==========================================================
     275        $this->imgdata_large[5][0]= 905 ;
     276        $this->imgdata_large[5][1]=
     277            'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAABO1'.
     278            'BMVEX////////3///39/fv7+/e5+fW3t7Wzs7WxsbG1tbGzsbG'.
     279            'xsbDxMS/v7++wMC+v7+9zsa9xsa9vb29tbW9ra29pa24uLi1xs'.
     280            'a1vb21tbWxtrattbWmpqalra2cra2cpaWcnJycjIyUpaWUnJyU'.
     281            'lJSUjIyMnJyMnJSMlJSMlIyMjJSMjIyElJSElIyEjIyEhIR7jI'.
     282            'x7hIR7hHt7e3t7e3N7e2tzhIRze3tze3Nzc3Nre3trc3Nrc2tr'.
     283            'a2tjc3Njc2tja3Nja2tjY2NjWlpaa2taY2taY2NaY1paWlpaUl'.
     284            'JSY2NSY1pSWlpSWlJSUlJSUkpKWlpKWlJKUlpKUlJKUkpKSkpK'.
     285            'SkJCUlJCUkJCSkpCSkJCQkI5Sko5QkI5Qjk5OUI5OTkxQkIxOT'.
     286            'kxMTkxMTEpMTEhMTEhKSkYISEpy7AFAAAAAXRSTlMAQObYZgAA'.
     287            'AAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdE'.
     288            'lNRQfTAwkRFQfW40uLAAABx0lEQVR4nI3SbXfSMBQA4NV3nce5'.
     289            'TecAHUywRMHSgFuBCFsQUqwBS1OsWQh0GTj//y8wZUzdwQ/efM'.
     290            'tzcm/uuXdj4z9ic/PR9k4qk1qDnf0X2/uZzKt8GaRvSubg4LVp'.
     291            'mkWzCGAT/i3Zsm2XNQHLsm2n2937LaaNnGoJFAEo27B50qN0ay'.
     292            'Wg26lXsw8fP8nmzcJb2CbsnF5JmmCE8ncN404KvLfsYwd7/MdV'.
     293            'Pdgl/VbKMIzbuwVgVZw2JlSKJTVJ3609vWUY957lgAUd1KNcqr'.
     294            'yWnOcOPn8q7d5/8PywAqsOOiVDrn42NFk+HQ7dVuXNYeFdBTpN'.
     295            'nY5JdZl8xI5Y+HXYaTVqEDp1hAnRohZM03EUjMdhn5wghOoNnD'.
     296            'wSK7KiiDPqEtz+iD4ctdyAifNYzUnScBSxwPd6GLfRURW7Ay5i'.
     297            'pS5bmrY8348C5vvUI+TLiIVSJrVA0heK/GDkJxYMRoyfCSmk4s'.
     298            'uWc3yic/oBo4yF374LGQs5Xw0GyQljI8bYmEsxVUoKxa6HMpAT'.
     299            'vgyhU2mR8uU1pXmsa8ezqb6U4mwWF/5MeY8uLtQ0nmmQ8UWYvb'.
     300            'EcJaYWar7QhztrO5Wr4Q4hDbAG/4hfTAF2iCiWrCEAAAAASUVO'.
     301            'RK5CYII=' ;
     302
     303//==========================================================
     304// File: bl_brown.png
     305//==========================================================
     306        $this->imgdata_large[6][0]= 1053 ;
     307        $this->imgdata_large[6][1]=
     308            'iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAABoV'.
     309            'BMVEX////Gzs7GvbXGrZTGpXu9nHO1nHO1nIy9taXGxs7GtaXO'.
     310            'nHPGlFrGjEq9hEq1hEqte0Klczmcazmce1KtnIzGxsbGvb3OlF'.
     311            'LOlFq9hFKte0qcc0KUYzGEWimMc1K9ta3OnGvOnGPWnGO9jFq9'.
     312            'jFKlc0KUazmMYzl7UilzUjGtpZzGxr3GnGPWpWvepXO1hFJ7Wj'.
     313            'FrSiFjUjG1ra3GnHPvxpT/5733zpythFKUa0KEYzlzUilaOSF7'.
     314            'Wjm9jErvvYz/99b///f/78bnrYS1hFqle0p7UjFrSiljQiFCMR'.
     315            'iMhHO9lGvGjFLWnGv/3q3////erXuthEqlc0paQiFKMRhSQin/'.
     316            '1qX/997//++cc0pjSilaQilKORhCKRiclIy9pYzGlGPntYT33q'.
     317            '3vvZSEWjlSOSE5KRB7c2O1lHutczmthFqte1JrWkqtjGtCKRBa'.
     318            'SjmljGuca0KMYzGMaznOztaclISUYzmEWjFKOSF7a1qEYzFaSi'.
     319            'GUjISEa0pKOSm9vb2llIxaQhg5IQiEc2tzY0paORilnJy1raVS'.
     320            'OSljUkJjWkKTpvQWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'.
     321            'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkREiei'.
     322            'zP2EAAAB9UlEQVR4nGWS/VfSUBjHL5QluhhBxtwyWcCus5Blpm'.
     323            'wDC4ONaWXCyBi7RMZmpQ2Bypm9W/byV3cHHo/W88s95/s5z/d5'.
     324            'uwCcCh/4L3zAf+bs0NC588On9QAYGSUuBINk6GI4cmnsBLk8Go'.
     325            '1SFEGMkzRzZeLq5JE8FvDHouw1lqXiCZJOcnCKnx4AcP0GBqmZ'.
     326            'mRgRT9MMB4Wbs7cGSXNRik3dnp9fiMUzNCNKgpzN9bsaWaQo9s'.
     327            '7dfH7pXiFTZCBU1JK27LmtBO8TDx7mV1eXHqXXyiIUFLWiVzHx'.
     328            'BxcJIvV4/cn6wkqmWOOwmVE3UQOAp6HxRKL5bGPj+VwhUhalFq'.
     329            '8alm5vAt+LlySZTsebzcKrraIIW4JqZC3N3ga+1+EQTZKZta1M'.
     330            'pCZCSeDViqVrThsEdsLJZLJYLpZrHVGScrKBvTQNtQHY6XIM02'.
     331            'E6Ik7odRW1Dzy3N28n3kGuB3tQagm7UMBFXI/sATAs7L5vdbEs'.
     332            '8Lycm923NB0j5wMe6KOsKIIyxcuqauxbrmlqyEWfPmPy5assY1'.
     333            'U1SvWKZWom9nK/HfQ3+v2HYZSMStayTNN0PYKqg11P1nWsWq7u'.
     334            '4gJeY8g9PLrddNXRdW8Iryv86I3ja/9s26gvukhDdvUQnIjlKr'.
     335            'IdZCNH+3Xw779qbG63f//ZOzb6C4+ofdbzERrSAAAAAElFTkSu'.
     336            'QmCC' ;
     337
     338//==========================================================
     339// File: bl_darkgreen.png
     340//==========================================================
     341        $this->imgdata_large[7][0]= 1113 ;
     342        $this->imgdata_large[7][1]=
     343            'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAB2l'.
     344            'BMVEX////////3///v///n/+/e99bW/+/W99bO786/v7++vr69'.
     345            '/96999a7wb24vbu1/9a1zqW1u7itxrWosq6l772l1qWlxrWlxq'.
     346            '2lva2cxpSU562U3q2UxqWUvaWUpZyM77WM57WMvYyMtZyMrZyM'.
     347            'pZSMnJSEvZyEtYyErZSElIx7zpR7xpx7xpR7vZR7jIRz1pRzxp'.
     348            'RzjIRrzpRrzoxrxoxrtYRrrYxrrXtrpYRrhHNjzoxjxoxjxoRj'.
     349            'vYRjtYRjrXtjpXtjlGNje2tazoxazoRaxoxaxoRavYRatYRatX'.
     350            'tarXtapXNanHNajFpae2tSzoRSxoRSvXtStXtSrXtSrXNSpXNS'.
     351            'nHNSnGtSlGtSlGNSjGtSjGNKvXtKtXNKrXNKpWtKnGtKlGNKjG'.
     352            'NKhGNKhFJKc1pKa1JCrWtCpWtCnGtClGNCjGNCjFpChFpCe1JC'.
     353            'a1JCY1I5pWs5nGM5lGM5jFo5hFo5e1o5c0o5WkoxjFoxhFoxhF'.
     354            'Ixe1Ixc1Ixc0oxa0ophFIpe0opc0opa0opa0IpY0IpWkIpWjkp'.
     355            'UkIpUjkhc0oha0IhY0IhWjkhWjEhUjkhUjEhSjEhSikhQjEhQi'.
     356            'kYWjkYSjEYSikYQjEYQikQSikQQikQQiEQOSExf8saAAAAAXRS'.
     357            'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'.
     358            'LdfvwAAAAHdElNRQfTAwkRFCaDkWqUAAAB+ElEQVR4nI3S+1vS'.
     359            'UBgHcGZlPV0ks/vFrmQWFimJjiwiYUJWjFBWFhClyZCy5hLrwA'.
     360            'x2EIwJC1w7zf2vnU0re+iHvs9++7x7zznvORbLf+TA6ct9fYMX'.
     361            'jrfAUYefpp+/iM1ykxf/lmuhUZ/PTwXC8dml5Wcd23o5H5Mk6b'.
     362            '5NUU8icXbhS67rNzn9JDnguOEYGQtEEtwC+Crs3RJ76P5A/znr'.
     363            'vsNX7wQnEiwHCtK7TTkW8rvdZ9uJtvZTLkxpHhSrP66bNEj7/P'.
     364            '3WNoLYeeSWQQCIpe9lQw7RNEU5rDsIYtcJ14Nocg7kRUlBNkxn'.
     365            'YmGKcp7cv3vPwR7XOJPmc0VYU3Sv0e9NOBAYG7Hbz/cMjTMveZ'.
     366            'CHkqxuTBv0PhYJB4N3XR6PJ5rMAPMnpGUxDX1IxSeMTEaZp1OZ'.
     367            'nGAIQiYtsalUIhFlmGTy3sO3AizJCKn6DKYryxzHsWyaneMzr6'.
     368            'cWxRVZVlFTe4SpE3zm+U/4+whyiwJcWVMQNr3XONirVWAklxcE'.
     369            'EdbqchPhjhVzGpeqhUKhWBQhLElr9fo3pDaQPrw5xOl1CGG1JE'.
     370            'k1uYEBIVkrb02+o6RItfq6rBhbw/tuINT96766KhuqYpY3UFPF'.
     371            'BbY/19yZ1XF1U0UNBa9T7rZsz80K0jWk6bpWGW55UzbvTHZ+3t'.
     372            'vbAv/IT+K1uCmhIrKJAAAAAElFTkSuQmCC' ;
     373
     374//==========================================================
     375// File: bl_green.png
     376//==========================================================
     377        $this->imgdata_large[8][0]= 1484 ;
     378        $this->imgdata_large[8][1]=
     379            'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABm'.
     380            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
     381            'B3RJTUUH0wMMFjM4kcoDJQAABVlJREFUeNq9ll2MJFUVx3/11V'.
     382            'Vd/TE9vU0v4zLDwJIF16jBqLAPhsRXEiDqg0QTJiQSjcSNvCzw'.
     383            'sBEDDxizhvAAxBgf1oR9QF9NiE9ESFZkQyZB5WtddmdnZ3qqqr'.
     384            'uqbt367Cofqu3ZZpWVaDzJfbkf53//55z/PVdZXV3l/2H6f7Lp'.
     385            '5VdOV/4Nb+GmHpUeA7AdBNxc3kafNb73jRPK9Xwon8ToxVefqU'.
     386            'b91wibH5EkCQBCizFihTSviHUHR0hWws9xe3wvJ7/7nPKpgX5y'.
     387            '9oFqt3eOgWniRBoAbUBGGqZUibSYaeoT2B5bnkdaSA6793Cv/S'.
     388            'QPPbihXBfo5VdOV+8dfgnvwAU62YH5fCZ12sDujFkwyegCqTrB'.
     389            'iUOKTOJKj8jr88jS8zy6cXwBTP048nuHX0I0nDlIp7RpTG7kM0'.
     390            'sdyAYsTVukUuWGhlWHMq0ITL92lnUp9R1Obz/GmTNnqn9bDD8/'.
     391            '+0D1oX0O0zQZZDYCsK2j3Gl9jQqDfHiei8GfiKVLlsZkJaBAN1'.
     392            '0i6PgwUbB0GxG5/PrtE/xLRr959Znqw9452oVNI+jiJhnr1pe4'.
     393            'k29zB1/nFr5Kj7tpt1YYhJ0FJ7nUYbcJQBgahN2MzeCP/OipR6'.
     394            'prgN6Qr6ELFQFUWoRpNVjlKwxZB8DCpE+PtfEKqV1cUzxpVudu'.
     395            'GTBHA5Y1g99e+dUio9O/P1Vpq+/WE5GGjDSMoAtAQjrf3C52IP'.
     396            'QxpY4WK2hpReka9Gfrhqgz0bACRoCWjDh56kQ1z9FeuUUQxVhK'.
     397            'B92sD1VahM+bAJgcoJhGjP/6Ln8rAgDiRCVRKiIzxMkkodBJ85'.
     398            'im1IlEHbE4k1xyNveL4YP8HarmGJIOpqyjeQmfNHmTvnqZTWBt'.
     399            'vIJXpPwlukJSuSTKGK3pEwtJmiX00ZlInTyNscImO6XBITvH1c'.
     400            '8vVt2OucdKvIyeKRTNCivsEMgcpg6taYs30nfq0Gqg6hOSSFJ4'.
     401            'BSnJPht0IqEjWmOGocEI6F0J94F0qaL6BntTF0MtUfweKQKAPU'.
     402            'Wwp4OcVnQAmVb0p9DLOzjEhEKnGRmoRc7EzRGlwA6NujAKG4yP'.
     403            '6Sjwc4aVznZ7DK0xXdkDoJf0kGmFBniFBOBGcZSCCSKd0IwN0k'.
     404            'IS+QZWCGVZex4BnUxya3+Zt9iugQbcRFpIAtuHvAZulPUdLhUJ'.
     405            'RqegI3WcqaSXddlT3idsWMSRRGkEtNwmyTifAwyBo7LP+11J0e'.
     406            '7tM7pZOYblHkBLcqZ5LcYtw6Wbd4CM3SpE9foYZsIHoqDKCrbz'.
     407            'mLSQtPwmuhXgtBLs0GBdbXOhFGB7WBKO2F8GXt9/VO97Ya3atF'.
     408            '7nUHnwGjGGQqcPxFEdFqURkEidiZszAERoYIsGju1hq21kWee3'.
     409            'bw15+8WpsvAy3K1+i3JkkhZyPpxxjjPOsfOYiZ+TFhLPzQnHOU'.
     410            'tpzGB2dgA4tscIkKIx19Cxg/fPL7vQJu47eXt1VvsDK8pwPueZ'.
     411            'PuZoQMOqhRoJHSs0kKLBWjvjYinmeQGw1TaX1RFdfZ3LMzYLjA'.
     412            'C++dkn6AaH2Nobk6cxEzdnuG0TdC8zvdJkN0hqkFkO/jwL0fxa'.
     413            'so8sBcuFzQ+/+MRC+BeAHnpwQzn++ee5KT9Eshuy46dcKAXm32'.
     414            '0uzPQhS4GttkH2GQID2Wc0Y4LtAbDxhZ/x5A+e/uTG9+jGceXH'.
     415            '9/ySnnIXnUzOxXe1038mW3ZynNmam4yYWkO+f9cv+Oljz16/lV'.
     416            '9tDz/9nerc1hm8ZEScSRK7VvtYl1i1dklsOKyvc+zg/bzw1O8+'.
     417            '/efkajt56kR1ydlEJBc5H46xzbrJ3dY9wrB7hGcff+6/+279L+'.
     418            '0fHxyiE8XMLl4AAAAASUVORK5CYII=' ;
     419
     420//==========================================================
     421// File: bl_blue.png
     422//==========================================================
     423        $this->imgdata_large[9][0]= 1169 ;
     424        $this->imgdata_large[9][1]=
     425            'iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAACEF'.
     426            'BMVEX/////////7//35//v1v/exv/Wvf/Wrf/Wpf/Orf+/v7+9'.
     427            'tc69jP+9hP+5ucW1tc6tlP+rq7Wlpdalpcalpb2cnM6cnMacc/'.
     428            '+cWv+UlLWUjN6UjK2Uc/+Ma/+MUv+EhKWEa/+EQvd7e8Z7e7V7'.
     429            'e6V7c957Wv9za9Zza8ZzSv9ra5xrSv9rOf9rMe9jUudjQv9jOe'.
     430            '9aWpRaUt5aUpRaSu9aSudSUoxSSs5SSoxSMf9KQtZKOfdKMedK'.
     431            'Kf9KKe9CKf9CKb1CKa1CIfdCIedCId45MXs5Kfc5If85Iec5Id'.
     432            'Y5GP8xMbUxMXsxKc4xKZQxIf8xGP8xGO8xGN4xGNYxGL0xGK0p'.
     433            'KXMpIYwpGP8pGO8pGOcpGNYpGM4pEP8pEPcpEOcpEN4pENYpEM'.
     434            'YpEL0hGKUhEP8hEPchEO8hEOchEN4hENYhEM4hEMYhELUhCP8h'.
     435            'CO8hCN4YGJwYGGsYEL0YEK0YEHMYCN4YCM4YCMYYCL0YCKUYAP'.
     436            '8QEJQQEIwQEHsQEGsQCM4QCLUQCK0QCKUQCJwQCJQQCIwQCHMQ'.
     437            'CGsQAP8QAPcQAO8QAOcQAN4QANYQAM4QAMYQAL0QALUQAKUQAJ'.
     438            'QQAIQICGsICGMIAO8IANYIAL0IALUIAK0IAKUIAJwIAJQIAIwI'.
     439            'AIQIAHsIAHMIAGsIAGMAAN4AAMYAAK0AAJQAAIwAAIQAAHMAAG'.
     440            'sAAGMAAFrR1dDlAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
     441            'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkRFRPMOZ'.
     442            '/2AAAB+klEQVR4nGNgIAIIqeqZmBqpi2JISNml5lVXV3d198Yo'.
     443            'oUjwm1SnxsbGRsSm5ZfNXO4tjCTjVh0ABhFx6QV9E1Y0S8JkuN'.
     444            '3yAgLc7W3t/QPi4jPKJ8ye1yoIlTKpjvVy15eVUbN0i4zKLJ8w'.
     445            'ae6qcKgLqmMj3PUFWFl5NJ0CExLLJzbNW7BWCyxlXR0ba6/Axs'.
     446            'zELmfnkRBT0QiSKgXJCOflxUbYy3KyMHEoOrtEZ1c2TZ6/cMl6'.
     447            'eaCUamdsbIC7tjgPr4SBS3BMMVDTwkXr1hsDpYy6UmMj/O0tdX'.
     448            'QNbDxjknJLWqYsXLx0vStQynxGflpkZGCgs7Onp29SbtNkoMy6'.
     449            'pevCgFJWy3oyMuKjgoKCPWNCvEuqWhcsWrJ06XqQlPnMvrKyrM'.
     450            'TomJjkZAfHlNa2qdOWrlu63gcopbG8v7+hvLwip7g4JdSxsLZu'.
     451            '8dKlS9ettwBKic2eNXHChIkTG5tKqgpr2uo6loLAehWQx0LnzJ'.
     452            '49p6mpeXLLlNq6RUvqly6dvnR9Bx9ISnnlvLmT582bMr9t4aL2'.
     453            '+vrp60GaDCGB6Ld6wfwFCxYCJZYsXQ+SmL6+FBryInVrFi1atH'.
     454            'jJkqVQsH6pNCzCJNvXrQW6CmQJREYFEc2CYevXrwMLAyXXl0oz'.
     455            'IAOt0vVQUGSIkabkDV3DwlzNVDAksAAAfUbNQRCwr88AAAAASU'.
     456            'VORK5CYII=' ;
     457
     458//==========================================================
     459// File: bs_red.png
     460//==========================================================
     461        $this->imgdata_small[0][0]= 437 ;
     462        $this->imgdata_small[0][1]=
     463            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'.
     464            'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'.
     465            'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'.
     466            'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'.
     467            'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'.
     468            'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
     469            'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGDNEMgOYAAAAm0'.
     470            'lEQVR4nI3Q3RKCIBAFYGZMy9RKzX7MVUAUlQTe/+kS0K49d3wD'.
     471            '7JlFaG+CvIR3FvzPXgpLatxevVVS+Jzv0BDGk/UJwOkQ1ph2g/'.
     472            'Ct5ACX4wNT1o/zzUoJUFUGBiGfVnDTYGJgmrWy8iKEtp0Bpd2d'.
     473            'jLGu56MB7f4JOOfDJAwoNwslk/jOUi+Jts6RVNrC1hkhPy50Ef'.
     474            'u79/ADQMQSGQ8bBywAAAAASUVORK5CYII=' ;
     475
     476
     477//==========================================================
     478// File: bs_lightblue.png
     479//==========================================================
     480        $this->imgdata_small[1][0]= 657 ;
     481        $this->imgdata_small[1][1]=
     482            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABVl'.
     483            'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'.
     484            'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'.
     485            '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'.
     486            'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'.
     487            'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'.
     488            'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'.
     489            'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'.
     490            'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'.
     491            'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'.
     492            'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'.
     493            'gAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGTok'.
     494            '9Yp9AAAAtElEQVR4nGNgIBaw8wkpKghzwvksPAKiUsraprYiLF'.
     495            'ARXkE2JiZ1PXMHXzGIAIekOFBE08TGLTCOCyzCLyvDxsZqZOnk'.
     496            'E56kAhaRV9NQUjW2tPcMjs9wBYsY6Oobmlk7egRGpxZmgkW0zC'.
     497            '2s7Jy9giKT8gohaiQcnVzc/UNjkrMLCyHmcHr7BYREJKTlFxbm'.
     498            'QOxiEIuKTUzJKgQCaZibpdOzQfwCOZibGRi4dcJyw3S4iQ4HAL'.
     499            'qvIlIAMH7YAAAAAElFTkSuQmCC' ;
     500
     501//==========================================================
     502// File: bs_gray.png
     503//==========================================================
     504        $this->imgdata_small[2][0]= 550 ;
     505        $this->imgdata_small[2][1]=
     506            'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAMAAADH72RtAAABI1'.
     507            'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'.
     508            'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'.
     509            'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'.
     510            'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'.
     511            'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'.
     512            'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'.
     513            '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'.
     514            'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'.
     515            'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIA'.
     516            'AAsSAdLdfvwAAAAHdElNRQfTAwkUGiIctEHoAAAAfElEQVR4nI'.
     517            '2N2xKDIAwF+bZ2kAa8cNFosBD//yvKWGh9dN+yk9kjxH28R7ze'.
     518            'wzBOYSX6CaNB927Z9qZ66KTSNmBM7UU9Hx2c5qjmJaWCaV5j4t'.
     519            'o1ANr40sn5a+x4biElrqHgrXMeac/c1nEpFHG0LSFoo/jO/BeF'.
     520            'lJnFbT58ayUf0BpA8wAAAABJRU5ErkJggg==' ;
     521
     522//==========================================================
     523// File: bs_greenblue.png
     524//==========================================================
     525        $this->imgdata_small[3][0]= 503 ;
     526        $this->imgdata_small[3][1]=
     527            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAxl'.
     528            'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'.
     529            '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'.
     530            '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'.
     531            'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'.
     532            'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'.
     533            'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'.
     534            'dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfT'.
     535            'AwkUGTIqLgJPAAAAqklEQVR4nI2QVxOCMBCEM6Mi2OiCvSslJB'.
     536            'CUoqjn//9TYgCfubf9Zu9uZxFqO+rscO7b6l/LljMZX29J2pNr'.
     537            'YjmX4ZaIEs2NeiWO19NNacl8rHAyD4LR6jjw6PMRdTjZE0JOiU'.
     538            'dDv2ALTlzRvSdCCfAHGCc7yRPSrAQRQOWxKc3C/IUjBlDdUcM8'.
     539            '97vFGwBY9QsZGBc/A4DWZNbeXIPWZEZI0c2lqSute/gCO9MXGY'.
     540            '4/IOkAAAAASUVORK5CYII=' ;
     541
     542//==========================================================
     543// File: bs_yellow.png
     544//==========================================================
     545        $this->imgdata_small[4][0]= 507 ;
     546        $this->imgdata_small[4][1]=
     547            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAzF'.
     548            'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'.
     549            'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'.
     550            'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'.
     551            'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'.
     552            'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'.
     553            '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'.
     554            'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAH'.
     555            'dElNRQfTAwkUGSDZl3MHAAAAqElEQVR4nI3QWRNDMBAA4My09E'.
     556            'IF1SME0VT1okXvM/3//6kEfbZv+81eswA0DfHxRpOV+M+zkDGG'.
     557            'rL63zCoJ2ef2RLZDIqNqYexyvFrY9ePkxGWdpvfzC7tEGtIRly'.
     558            'nqzboFKMlizAXbNnZyiFUKAy4bZ+B6W0lRaQDLmg4h/k7eFwDL'.
     559            'OWIky8qhXUBQ7gKGmsxpC+ah1TdriwByqG8GQNDNr6kLjf/wAx'.
     560            'KgEq+FpPbfAAAAAElFTkSuQmCC' ;
     561
     562//==========================================================
     563// File: bs_darkgray.png
     564//==========================================================
     565        $this->imgdata_small[5][0]= 611 ;
     566        $this->imgdata_small[5][1]=
     567            'iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAABJl'.
     568            'BMVEX////////o8v/f6O7W4OnR3PXL1OTL0evEyLvCzePAwMC/'.
     569            'v7a8wsq7t7C1xum1vtS1q6GzopmyxeKsrsOqvNWoq7anvN+nsb'.
     570            'qhrcGgqbGfpq6cp7+bqMuVmJKRm7yPlKKMnL6FkKWFipOEkLSE'.
     571            'j6qEhoqAiaB+jqd8haF7hZR4iJt4g5l3hZl2gIt2cod1hJVzeY'.
     572            'VzboJvhp9sfJJsb41peY1pd5xpdoVod4xndI5lcHxka4BjcYVg'.
     573            'Z3BfboFbb4lbZnZbYntaZ4laZYVZV3JYYWpXX3JWWm5VX4RVW2'.
     574            'NUYX9SXHxPWn5OVFxNWWtNVXVMVWFKV3xHUGZGU3dGTldFSlxE'.
     575            'Sk9ESXBCRlNBS3k/SGs/RU4+R1k9R2U6RFU2PUg0PEQxNU0ECL'.
     576            'QWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAA'.
     577            'CxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGQmbJetrAAAAtklEQV'.
     578            'R4nGNgwAK4JZTNNOWlYDxhMT4ZDTOzQE1uMF9CiJWVU0LbxDlS'.
     579            'G8QVF+FnZ2KRNHAIiPUHaZGSlmZj5lH19A1KjLUA8lXU5MWllF'.
     580            'yjo30TYr2BfG19G11b37CEeN84H38gX1HbwTUkOjo+zjfG3hLI'.
     581            'l1exCvCNCwnxjfMz0gTyRdXNHXx9fUNCQu2MwU6SN3ZwD42LCH'.
     582            'W30IK4T8vUJSAkNMhDiwPqYiktXWN9JZj7UQAAjWEfhlG+kScA'.
     583            'AAAASUVORK5CYII=' ;
     584
     585
     586//==========================================================
     587// File: bs_darkgreen.png
     588//==========================================================
     589        $this->imgdata_small[6][0]= 666 ;
     590        $this->imgdata_small[6][1]=
     591            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABX1'.
     592            'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'.
     593            'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'.
     594            'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'.
     595            'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'.
     596            '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'.
     597            'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'.
     598            'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'.
     599            'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'.
     600            'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'.
     601            'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'.
     602            'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
     603            'RQfTAwkUGRjxlcuZAAAAtElEQVR4nGNgIBZw8osqqIpzw/msfI'.
     604            'IiUmr6lo6SbFARASEOJiYtQ2uXADmIAJeEGFBE18LBMySBBywi'.
     605            'LC/LwcFiZuvmH5WiAxZR0tRW1DC3dfYJS8zyAouYGBibWtm7+o'.
     606            'TEpZfkgEX0rG3snNx9Q2NSCksgaqRd3Ty8gyLiU/NKSiDmcPsF'.
     607            'BodHJ2UUlZTkQ+xikIlNSE7LLgECZagL2VQyc0H8YnV2uD94jS'.
     608            'ILIo14iQ4HALarJBNwbJVNAAAAAElFTkSuQmCC' ;
     609
     610//==========================================================
     611// File: bs_purple.png
     612//==========================================================
     613        $this->imgdata_small[7][0]= 447 ;
     614        $this->imgdata_small[7][1]=
     615            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAnF'.
     616            'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'.
     617            'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'.
     618            'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'.
     619            'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'.
     620            'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
     621            'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGS'.
     622            'o5QpoZAAAAnElEQVR4nI3Q2xJDMBAG4MyQokWrZz3oSkJISJH3'.
     623            'f7dK0Gv/Xb7J7vyzCK0NjtPsHuH/2wlhTE7LnTNLCO/TFQjjIp'.
     624            'hHAA6bY06LSqppMAY47x+04HXTba2kAFlmQKr+YuVDCGUG2k6/'.
     625            'rNwYK8rKwKCnPxHnVS0aA3rag4UQslUGhrlk0Kpv1+sx3tLZ6w'.
     626            'dtYemMkOsnz8R3V9/hB87DEu2Wos5+AAAAAElFTkSuQmCC' ;
     627
     628
     629//==========================================================
     630// File: bs_brown.png
     631//==========================================================
     632        $this->imgdata_small[8][0]= 677 ;
     633        $this->imgdata_small[8][1]=
     634            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABaF'.
     635            'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'.
     636            'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'.
     637            'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'.
     638            'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'.
     639            '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'.
     640            'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'.
     641            'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'.
     642            'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'.
     643            'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'.
     644            'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'.
     645            'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLd'.
     646            'fvwAAAAHdElNRQfTAwkUGho0tvl2AAAAtklEQVR4nGNgIBaoSg'.
     647            'mLKGpowfkGMty8AqJKpi4mRlAROR5ONg4JFUv3YHOIgDo/HwsT'.
     648            'q6yps29EsjZYREFIkJ2ZS9/OMzA20wEsIi8uKSZtaOPmH5WSFw'.
     649            'YW0VRW07Vw8vCLSMguLwCL6FlaObp6B0TGZxSXQ9TouHv6+IXG'.
     650            'JGYWlpdDzNEKCgmPjkvLKS0vL4LYxWAen5SelV8OBNZQFxrZ5h'.
     651            'aC+GX2MDczMBh7pZakehkTHQ4AA0Am/jsB5gkAAAAASUVORK5C'.
     652            'YII=' ;
     653
     654//==========================================================
     655// File: bs_blue.png
     656//==========================================================
     657        $this->imgdata_small[9][0]= 436 ;
     658        $this->imgdata_small[9][1]=
     659            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAk1'.
     660            'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'.
     661            'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'.
     662            'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'.
     663            'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'.
     664            'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
     665            'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGhNNakHSAAAAmk'.
     666            'lEQVR4nI3P2xKCIBAGYGfM6SBWo1nauIqogaDA+z9dK9Lhrv47'.
     667            'vtl/2A2CfxNlJRRp9IETYGraJeEb7ocLNKznia8A7Db7umWDUG'.
     668            'sxAzhurxRHxok4KQGqCuEhlL45oU1D2w5BztY4KRhj/bCAsetM'.
     669            '2uObjwvY8/oX50JItYDxSyZSTrO2mNhvGMbaWAevnbFIcpuTr7'.
     670            't+5AkyfBIKSJHdSQAAAABJRU5ErkJggg==' ;
     671
     672//==========================================================
     673// File: bs_green.png
     674//==========================================================
     675        $this->imgdata_small[10][0]= 452 ;
     676        $this->imgdata_small[10][1]=
     677            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAn1'.
     678            'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'.
     679            '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'.
     680            'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'.
     681            '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'.
     682            'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'.
     683            'AIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAw'.
     684            'kUGgW5vvSDAAAAnklEQVR4nI3QSxKCMAwA0M4gqCgoiiJ+kEAL'.
     685            'LQUq0PufzX7ENdnlJZNkgtDS2CYZvK6bf+7EoKLA9cH5SQzv6A'.
     686            'YloTywsAbYr44FrlgrXCMJwHl3xxVtuuFkJAPIcw2tGB9GcFli'.
     687            'oqEf5GTkSUhVMw2TtD0XSlnDOw3SznE5520vNEi7CwW9+Ayjyq'.
     688            'U/3+yPuq5gvhkhL0xlGnqL//AFf14UIh4mkEkAAAAASUVORK5C'.
     689            'YII=' ;
     690
     691
     692//==========================================================
     693// File: bs_white.png
     694//==========================================================
     695        $this->imgdata_small[11][0]= 480 ;
     696        $this->imgdata_small[11][1]=
     697            'iVBORw0KGgoAAAANSUhEUgAAABEAAAAQCAYAAADwMZRfAAAABm'.
     698            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
     699            'B3RJTUUH0wMLFTsY/ewvBQAAAW1JREFUeJytkz2u4jAUhT/jic'.
     700            'gfBUKiZhE0bIKeVbCWrIKenp6eDiGlCEEEBArIxvzGU4xeZjLk'.
     701            'jWb05lRXuvbx+exr4bouX1Xjyw7Atz81F4uFBYjjGIDhcCjq1o'.
     702            'k6nN1uZwFerxfP55Msy1itVmRZBsB4PK6YveHkeW5d18XzPIIg'.
     703            'wPd9Wq0WnU6HMAxJkoQoiuynOIfDwUopkVIihKAoCgAcx6Hdbm'.
     704            'OMIU1T5vN55eBKEikljUYDIX6kFUKU9e8aDAZlmjcca+1b7TgO'.
     705            '1+uVy+VS9nzfr8e53++VzdZaiqIgz3OMMWitOZ/PaK0JgqDeRC'.
     706            'mF53lIKYGfr3O73TDGoJQiTVO01nS73XqT4/FIs9kkCAIej0eZ'.
     707            'brPZEMcxSZKgtQZgMpmIWpN+vy+m06n1PK9yTx8Gy+WS/X5Pr9'.
     708            'er9GuHLYoiG4YhSilOpxPr9Zrtdlti/JriU5MPjUYjq7UuEWaz'.
     709            '2d+P/b/qv/zi75oetJcv7QQXAAAAAElFTkSuQmCC' ;
     710
     711
     712//==========================================================
     713// File: bs_cyan.png
     714//==========================================================
     715        $this->imgdata_small[12][0]= 633 ;
     716        $this->imgdata_small[12][1]=
     717            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAABPl'.
     718            'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'.
     719            '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'.
     720            'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'.
     721            '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'.
     722            'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'.
     723            '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'.
     724            '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'.
     725            'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'.
     726            'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'.
     727            'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
     728            'AHdElNRQfTAwkUGQDi+VPPAAAAtElEQVR4nGNgIBawikipyIiy'.
     729            'wfksfJpGRkamNtr8LFARPiMFHmFDcztXfwGoFi0jLiZuZRtnry'.
     730            'BddrCIiJEGL6eklYO7X3iCOFhE2thESdHawdUnJDZFDiyiamZh'.
     731            'aevk5h0UlZSpBhaRtbN3dPHwDY5MSM+EqBFzc/f0DgiLTkjLzI'.
     732            'SYw6bjHxgaEZeckZmpD7GLQSAqJj4xNRMIBGFuFtRLA/ENhGBu'.
     733            'ZmDgkJBXl5fgIDocAAKcINaFePT4AAAAAElFTkSuQmCC' ;
     734
     735//==========================================================
     736// File: bs_bluegreen.png
     737//==========================================================
     738        $this->imgdata_small[13][0]= 493 ;
     739        $this->imgdata_small[13][1]=
     740            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAvV'.
     741            'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'.
     742            'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'.
     743            '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'.
     744            'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'.
     745            '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'.
     746            'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'.
     747            'AJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGxNUcXCT'.
     748            'AAAAqUlEQVR4nI2Q1xKCMBREM2NHLCCogAGCjd6SqLT8/2cZKT'.
     749            '6zb3tm987OBWCsXoejp8rC35fi4+l6gXFZlD0Rz6fZ1tdDmKR9'.
     750            'RdOmkzmP7DDpilfX3SzvRgQ/Vr1uiZplfsCBiVf03RJd140wgj'.
     751            'kmNqMtuYXcxyYmNWJdRoYwzpM9qRvGujuCmSR7q7ARY00/MiWk'.
     752            'sCnjkobNEm1+HknDZgAqR0GKU43+wxdu2hYzbsHU6AAAAABJRU'.
     753            '5ErkJggg==' ;
     754
     755//==========================================================
     756// File: bs_lightred.png
     757//==========================================================
     758        $this->imgdata_small[14][0]= 532 ;
     759        $this->imgdata_small[14][1]=
     760            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAA3l'.
     761            'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'.
     762            'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'.
     763            'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'.
     764            'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'.
     765            'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'.
     766            'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'.
     767            'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
     768            'cwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAwkUGjoP2Nm+AAAAr0'.
     769            'lEQVR4nGNgIBaYiOk62imYwPnMkiIyso76yhJSzFARMxkRNk49'.
     770            'a3t5OW6oFk1LVkYOfWUHKxUXiEYzLS12DnN3VXkjIRtFsIiSk5'.
     771            '6evqGqhYGKugAfWMRa1FpD2UHeQEXQRlgALCJur+rgbCUNFOAS'.
     772            'hqjRkZe3MpBTcwEKCEPMMTGSs3Xz8OQHCnBBHckt6OJpIyAMBD'.
     773            'wwN/MYc4H4LK4wNzMwmGrzcvFqmxIdDgDiHRT6VVQkrAAAAABJ'.
     774            'RU5ErkJggg==' ;
     775
     776//==========================================================
     777// File: bxs_lightred.png
     778//==========================================================
     779        $this->imgdata_xsmall[0][0]= 432 ;
     780        $this->imgdata_xsmall[0][1]=
     781            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAA3l'.
     782            'BMVEX///////+/v7/Gvb0hGBj/5///3v//zu//1u//xucpGCG9'.
     783            'nK21lKVSQkp7Wms5KTExISlaOUpjQlIhEBj/tdbOhKXnrcbGjK'.
     784            'Wla4TetcbGnK2EWmv/rc73pcZ7UmOcY3vOpbW1jJzenLW9e5Rz'.
     785            'Slq1c4xrQlJSOULGhJz/pcb3nL2chIzOnK33rcbelK3WjKWMWm'.
     786            'vGe5SEUmM5ISnOtb3GrbXerb3vpb2ca3v/rcaUY3POhJxCKTF7'.
     787            'SlrWnK21e4ytc4TvnLXnlK2la3taOUK1lJxrSlLGhJRjQkpSMT'.
     788            'lw+q2nAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
     789            'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKBOgGhWjAAAAS0'.
     790            'lEQVR4nGNgQAEmunYmEJaMCKe1vBxYzJKVQ9lKBSSupKdnaKGi'.
     791            'zgdkiqs6WKnYcIGYJnK2HvzCwmCNgi42wsLCECNMeXlNUY0HAL'.
     792            'DaB7Du8MiEAAAAAElFTkSuQmCC' ;
     793
     794//==========================================================
     795// File: bxs_bluegreen.png
     796//==========================================================
     797        $this->imgdata_xsmall[1][0]= 397 ;
     798        $this->imgdata_xsmall[1][1]=
     799            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAvV'.
     800            'BMVEX///////+/v79j//855/8x3v851v9Spb1C1v8AOUqEtcZK'.
     801            'lK1StdYxzv8hxv8AY4QASmNSlK1KpcZKtd4YQlIYnM4YrecIvf'.
     802            '8AtfcAre8AjL0AhLUAc5wAa5QAWnsAQloAKTkAGCFKhJxKrdYY'.
     803            'jL0Ypd4Atf8ArfcApecAnN4AlM4AjMYAe60Ac6UAY4wAUnNSnL'.
     804            '0AlNYAWoQASmsAOVIAITGEtc4YWnsAUnsAMUqtvcaErcYAKUIA'.
     805            'GCkAECHUyVh/AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAA'.
     806            'AJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUKDVyF5Be'.
     807            'AAAASUlEQVR4nGNgQAFmYqJcEJaEOJ+UrD5YTJKFTZrfGCQuaq'.
     808            'glLWvMaQ5kqujo6hnbKIKYXPr68gp2dmCNJiZAlh3ECGsREWtU'.
     809            '4wF1kwdpAHfnSwAAAABJRU5ErkJggg==' ;
     810
     811//==========================================================
     812// File: bxs_navy.png
     813//==========================================================
     814        $this->imgdata_xsmall[2][0]= 353 ;
     815        $this->imgdata_xsmall[2][1]=
     816            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'.
     817            'BMVEX///////+/v7+trcbGxv+EhM6EhNaEhP97e/9zc/9ra/9S'.
     818            'UsZKSrVSUs5jY/9SUtZKSsZSUudKSt5KSudKSv8YGIQpKf8YGK'.
     819            'UYGN4YGO8YGPcQEP8ICP8AAP8AAPcAAO8AAOcAAN4AANYAAM4A'.
     820            'AMYAAL0AALUAAK0AAKUAAJwAAJQAAIwAAIQAAHsAAHMAAGsAAG'.
     821            'ONFkFbAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
     822            'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJxXO4axZAAAAR0'.
     823            'lEQVR4nGNgQAGskhKsEJaslIi8ijpYTJaDU1FVAyQuKSujoKKh'.
     824            'LQ5kSigpqWro6oOYrOoaWroGBmCNWiCWAdQwUVFWVOMBOp4GCJ'.
     825            's5S60AAAAASUVORK5CYII=' ;
     826
     827//==========================================================
     828// File: bxs_gray.png
     829//==========================================================
     830        $this->imgdata_xsmall[3][0]= 492 ;
     831        $this->imgdata_xsmall[3][1]=
     832            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABI1'.
     833            'BMVEX///8AAAD8EAD8IAD8NAD8RAD8VAAYGBi/v7+goKCCgoJk'.
     834            'ZGRGRkb8yAD83AD87AD8/AD4+ADo+ADY+ADI+AC0+ACk+ACU+A'.
     835            'CE+AB0/ABk/ABU/ABE/AAw/AAg/AAQ/AAA/AAA+AAA6BAA2CAA'.
     836            'yDQAtEQApFQAlGQAhHQAdIgAZJgAVKgARLgAMMgAINwAEOwAAP'.
     837            'wAAPgIAPAQAOgYAOAkANgsANA0AMg8AMBEALhMALBUAKhcAKBo'.
     838            'AJhwAJB4AIiAAID////4+Pjy8vLs7Ozm5ubg4ODa2trT09PNzc'.
     839            '3Hx8fBwcG7u7u1tbWurq6oqKiioqKcnJyWlpaQkJCJiYmDg4N9'.
     840            'fX13d3dxcXFra2tkZGReXl5YWFhSUlJMTExGRkZAQEA1BLn4AA'.
     841            'AAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEA'.
     842            'AAsRAX9kX5EAAAAHdElNRQfTAwkUKC74clmyAAAAQklEQVR4nG'.
     843            'NgQAVBYVCGt5dXYEQ0mOnp5h4QFgVmeri6+4dHxYMVeHoFRUTH'.
     844            'gTUFBIZBWAwMkZEx8bFQM2Lj0UwHANc/DV6yq/BiAAAAAElFTk'.
     845            'SuQmCC' ;
     846
     847//==========================================================
     848// File: bxs_graypurple.png
     849//==========================================================
     850        $this->imgdata_xsmall[4][0]= 542 ;
     851        $this->imgdata_xsmall[4][1]=
     852            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABSl'.
     853            'BMVEX////////11P/MqdvKrNfAwMC+u7+9u7+4rr24lsi3rby3'.
     854            'lMe1rLq1o720q7i0oL20ksSzoryyqbaykMGxlb2wkL+vnbiujb'.
     855            '2sjLuri7qpl7GoirWoibenmK2mla6mjLKmhrSllauki7CjhrCj'.
     856            'hLGihLChg6+ggq2fkqadkKOcfqqai6Gag6WYe6WXeqSWeaOTd6'.
     857            'CTd5+Rdp6RdZ6RdZ2Qg5eOc5qMcpiLcZeJb5WIbpOHbZKGbJGE'.
     858            'a4+CaY2AZ4t/Z4p/Zop/Zol+Zol7ZIZ6Y4V5YoR1ZH11X391Xn'.
     859            '9zXX1yXXtxXHtvWnluWXhsV3VqVnNpVXJoVHFnU3BmUm9jUGth'.
     860            'VGdgTmheTGZcS2RcSmRaSWJYR19XRl5SQllRQlhQQVdPQFZOP1'.
     861            'VLPlFJO09IPE5IOk5FOEtEN0lDOEpDOElDNklCNkc/M0XhbrfD'.
     862            'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
     863            'EAAAsRAX9kX5EAAAAHdElNRQfTAwkUKCgREfyHAAAATUlEQVR4'.
     864            'nGNgQAEcIko8EBY3M5Ougy+IxSXMwmTsFsAHZMqrSRvZB0W7A5'.
     865            'k6FlYugXEZICaPr394Um4uSAFDRFRCbm4uxAihsDAhVOMBHT0L'.
     866            'hkeRpo8AAAAASUVORK5CYII=' ;
     867
     868//==========================================================
     869// File: bxs_red.png
     870//==========================================================
     871        $this->imgdata_xsmall[5][0]= 357 ;
     872        $this->imgdata_xsmall[5][1]=
     873            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAk1'.
     874            'BMVEX////////GxsbGra3/xsbOhITWhIT/hIT/e3v/c3P/a2vG'.
     875            'UlK1SkrOUlL/Y2PWUlLGSkrnUlLeSkrnSkr/SkqEGBj/KSmlGB'.
     876            'jeGBjvGBj3GBj/EBD/CAj/AAD3AADvAADnAADeAADWAADOAADG'.
     877            'AAC9AAC1AACtAAClAACcAACUAACMAACEAAB7AABzAABrAABjAA'.
     878            'BuukXBAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZ'.
     879            'cwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIyjy5SVMAAAAS0'.
     880            'lEQVR4nGNgQAFsUpJsEJastIi8ijpYTJaDU0FVgxXIlJKVUVDR'.
     881            '0BYHMiUUlVQ1dPVBTDZ1dS1dAwOQAgYtbSDLAGIEq6goK6rxAD'.
     882            'yXBg73lwGUAAAAAElFTkSuQmCC' ;
     883
     884//==========================================================
     885// File: bxs_yellow.png
     886//==========================================================
     887        $this->imgdata_xsmall[6][0]= 414 ;
     888        $this->imgdata_xsmall[6][1]=
     889            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAzF'.
     890            'BMVEX///////+/v79zYwCMewDOxoTWzoTezkr/5wj/5wDnzgDe'.
     891            'xgC1pQCtnACllACcjACUhABjWgDGvVK1rUrOxlLGvUqEexilnB'.
     892            'jv3hj35xj/7wj/7wD35wDv3gDn1gDezgDWxgDOvQDGtQC9rQCE'.
     893            'ewB7cwBzawBrYwDWzlLn3lLe1krn3kre1hi9tQC1rQCtpQClnA'.
     894            'CclACUjACMhAD/9wC/v7///8bOzoT//4T//3v//3P//2v//2Pn'.
     895            '50r//0r//yn39xj//xD//wBjYwDO8noaAAAAAXRSTlMAQObYZg'.
     896            'AAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAH'.
     897            'dElNRQfTAwkUIzoBXFQEAAAAS0lEQVR4nGNgQAFsDhJsEJaTo5'.
     898            '2skj5YzMnSSk7ZwBzIlOSUklPiMxYHMnW4FXT5VNVBTDZeXiNV'.
     899            'QUGQAgYBYyBLEGIEq5gYK6rxAH4kBmHBaMQQAAAAAElFTkSuQm'.
     900            'CC' ;
     901
     902//==========================================================
     903// File: bxs_greenblue.png
     904//==========================================================
     905        $this->imgdata_xsmall[7][0]= 410 ;
     906        $this->imgdata_xsmall[7][1]=
     907            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAxl'.
     908            'BMVEX///////+/v79znJQhSkJ7raU5hHtjraVKnJRCjIRClIyU'.
     909            '9++E595avbVaxr2/v7+ctbWcvb17nJxrjIx7paUxQkK9//+Mvb'.
     910            '17ra2Evb17tbVCY2MQGBiU5+ec9/eM5+d71tZanJxjra1rvb1j'.
     911            'tbVSnJxara1rzs5jxsZKlJRChIQpUlIhQkJatbVSpaU5c3MxY2'.
     912            'MYMTEQISFavb1Sra1KnJxCjIw5e3sxa2spWlpClJQhSkoYOTkp'.
     913            'Y2MhUlIQKSkIGBgQMTH+e30mAAAAAXRSTlMAQObYZgAAAAFiS0'.
     914            'dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfT'.
     915            'AwkUJy5/6kV9AAAATUlEQVR4nGNgQAGCyuyCEJaGugKHviVYzF'.
     916            'hO3sxCWwDIVNLTM9PXtpEGMhW12Cy0DR1ATEFLSxZ7BweQAgYd'.
     917            'HUMHBweIEQKiogKoxgMAo/4H5AfSehsAAAAASUVORK5CYII=' ;
     918
     919//==========================================================
     920// File: bxs_purple.png
     921//==========================================================
     922        $this->imgdata_xsmall[8][0]= 364 ;
     923        $this->imgdata_xsmall[8][1]=
     924            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAnF'.
     925            'BMVEX///////+/v7/Gvca9rb3Grcb/xv+1hLWte629hL21e7XG'.
     926            'hMbWhNbOe87We9b/hP//e/97OXv/c///a///Y/+cOZz/Sv/WOd'.
     927            'bnOefvOe//Kf9jCGNrCGv/EP//CP/nCOf/AP/3APfvAO/nAOfe'.
     928            'AN7WANbOAM7GAMa9AL21ALWtAK2lAKWcAJyUAJSMAIyEAIR7AH'.
     929            'tzAHNrAGtjAGPP1sZnAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
     930            'HUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUIj'.
     931            'mBTjT/AAAASUlEQVR4nGNgQAGskhKsEJaCrJiSuhZYTEFASFlD'.
     932            'GyQuqSCnrK6tJwpkiquoamgbGIGYrFpaugbGxmCNunpAljHECB'.
     933            'ZBQRZU4wFSMAZsXeM71AAAAABJRU5ErkJggg==' ;
     934
     935//==========================================================
     936// File: bxs_green.png
     937//==========================================================
     938        $this->imgdata_xsmall[9][0]= 370 ;
     939        $this->imgdata_xsmall[9][1]=
     940            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAn1'.
     941            'BMVEX///////+/v7+/v7/G/8aUxpSMvYyUzpSMzoyM1oxarVqE'.
     942            '/4R7/3tavVpKnEpaxlpz/3Nr/2tKtUpj/2Na51pKzkpK1kpK50'.
     943            'pK/0oYcxgp/ykYlBgY3hgY7xgY9xgQ/xAI/wgA/wAA9wAA7wAA'.
     944            '5wAA3gAA1gAAzgAAxgAAvQAAtQAArQAApQAAnAAAlAAAjAAAhA'.
     945            'AAewAAcwAAawAAYwA0tyxUAAAAAXRSTlMAQObYZgAAAAFiS0dE'.
     946            'AIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAw'.
     947            'kUKBrZxq0HAAAATElEQVR4nGNgQAGccrIcEJaivISyhjaIxa7I'.
     948            'I6CiqcMKZMopKqho6OhLA5kyqmqaOobGICartraeoYkJSAGDnj'.
     949            '6QZQIxgk1Skg3VeABlVgbItqEBUwAAAABJRU5ErkJggg==' ;
     950
     951//==========================================================
     952// File: bxs_darkgreen.png
     953//==========================================================
     954        $this->imgdata_xsmall[10][0]= 563 ;
     955        $this->imgdata_xsmall[10][1]=
     956            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABX1'.
     957            'BMVEX////////l/+nAwMC86r+8wb28wby8wLy78sCzw7SywrSx'.
     958            'wLKwvrGuvK+syK+ryq2rx62n36ym3aumxKmk2qij0Keh16ahva'.
     959            'Og1aSguKKe06KeuaCetZ+d0KGdtZ+bz6Cay56ZyZ2Zwp2Zr5qZ'.
     960            'rpqYwJuXyZuXrJmVw5mUxZiTxJeTw5eTq5WRwJWPtJKOvZKKuI'.
     961            '6Kt42Kn4yJt42ItIuGsomFsYmEsIiEr4eDr4eBrIR/qoN+qIJ8'.
     962            'poB7pH56o356on14nnt2nXl0mndzmnZzmXZymHVwlXNvlHJukn'.
     963            'FtiHBqjm1qjW1oi2toiWpniWplh2hlhmdkhWdig2VggGNgf2Je'.
     964            'fmFdfGBde19bbl1aeFxXdFpWclhVclhVcVdUcFZTb1VSbVRQal'.
     965            'JPaVFKY0xKYkxJYUtIYEpHX0lEWkZCWERCV0NCVkM/U0A+U0A+'.
     966            'UUA+UEA9Uj89UT48Tj45TDvewfrHAAAAAXRSTlMAQObYZgAAAA'.
     967            'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'.
     968            'RQfTAwkUKCFozUQjAAAATUlEQVR4nGNgQAGcoqrcEJYQB5OhSw'.
     969            'CIxSXGwWThGcIDZCppK5o7hyV6AZl6NnbuoSmFICZ3YHB0RkkJ'.
     970            'SAFDbEJaSUkJxAjeyEheVOMBQj4MOEkWew4AAAAASUVORK5CYI'.
     971            'I=' ;
     972
     973//==========================================================
     974// File: bxs_cyan.png
     975//==========================================================
     976        $this->imgdata_xsmall[11][0]= 530 ;
     977        $this->imgdata_xsmall[11][1]=
     978            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABPl'.
     979            'BMVEX////////F///AwMCvxsaC1NSC0dGCz8+CzMyA//94//91'.
     980            '//9q//9j//9X4uJX09NXz89Xx8dXxMRL//9L5uZL3d1L2NhLxs'.
     981            'ZLt7cv//8e9fUe8fEe7u4e398epqYehoYX//8L+PgK//8F9fUE'.
     982            '/v4E5+cEb28EZ2cC//8C/v4C/f0CzMwCrq4Cjo4CdXUCaWkCZW'.
     983            'UB/PwA//8A/f0A+/sA8/MA7e0A7OwA6+sA5eUA5OQA4uIA4eEA'.
     984            '3NwA2toA2NgA1dUA09MA0tIA0NAAysoAxsYAxcUAxMQAv78Avr'.
     985            '4AvLwAtrYAtbUAs7MAsLAAra0Aq6sAqKgApaUApKQAoqIAoKAA'.
     986            'n58AmpoAlZUAk5MAkpIAkJAAj48AjIwAiYkAh4cAf38AfX0Ae3'.
     987            'sAenoAcnIAcHAAa2sAaWkAaGgAYmIUPEuTAAAAAXRSTlMAQObY'.
     988            'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAA'.
     989            'AHdElNRQfTAwkUKQFKuFWqAAAATUlEQVR4nGNgQAGsUjJsEJaR'.
     990            'grC5qz9YzIiL28YriB3IlDZRsnYNiZUDMmXtHT2CE9JBTDb/wI'.
     991            'jkzEyQAoaomMTMzEyIERzy8hyoxgMAN2MLVPW0f4gAAAAASUVO'.
     992            'RK5CYII=' ;
     993
     994//==========================================================
     995// File: bxs_orange.png
     996//==========================================================
     997        $this->imgdata_xsmall[12][0]= 572 ;
     998        $this->imgdata_xsmall[12][1]=
     999            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABaF'.
     1000            'BMVEX//////////8X/3oD/3nj/1HX/0Gr/xGP/rkv/gBf+iS/2'.
     1001            'bAL1agDxaQDuZwDrZwLpZQDmZQLlZADjcx7gZATeYQDdZgraXw'.
     1002            'DZXwHYXgDXiEvXZAvUjlfUXwXTjVfTbR7ShUvRbR7RWwDMWQDL'.
     1003            'WADKooLKWADJoYLJgkvHWATGoILFn4LFgEvFVgDEZx7EVQDDt6'.
     1004            '/DVQDCt6/CnoLChlfCVADAwMC+hFe+UgC8UgC6UQC4gVe4UAC3'.
     1005            'gVe3UAC1gFe1eUu1TwC1TgCzTgCwTQKuTACrSgCqSgCpSgCpSQ'.
     1006            'CodEulSACkRwCiRgCdRACcRACaQwCYQgCWQgKVQQCVQACUQACS'.
     1007            'UR6RPwCOPgCNPQCLPACKPACJOwCEOQCBOAB+NwB9NgB8NgB7NQ'.
     1008            'B6NwJ4NAB3RR52MwB0MgBuLwBtLwBsLwBqLgBpLQBkLQJiKgBh'.
     1009            'KgBgKwRcKABbKQJbJwBaKQRaJwBYKAJVJQDZvdIYAAAAAXRSTl'.
     1010            'MAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9k'.
     1011            'X5EAAAAHdElNRQfTAwkUJBSSy88MAAAATUlEQVR4nGNgQAGqwo'.
     1012            'paEBYPJ4eKezCIpc7HwmrqG6ENZMpLihm6RaWEAZl6Vo7ekRnF'.
     1013            'IKZWSHhcTnk5SAFDfFJWeXk5xAjj1FRjVOMBeFwNcWYSLjsAAA'.
     1014            'AASUVORK5CYII=' ;
     1015
     1016//==========================================================
     1017// File: bxs_lightblue.png
     1018//==========================================================
     1019        $this->imgdata_xsmall[13][0]= 554 ;
     1020        $this->imgdata_xsmall[13][1]=
     1021            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAABVl'.
     1022            'BMVEX////////d///AwMC7wcS08P+y+P+xxdCwxM+uws2twMur'.
     1023            'vsinzNynytylzuKhyN6e5v6d5P+d1fOcwNWcu8ub4f+at8iZ3v'.
     1024            '+ZvdGY2/yW2f+VscGU1vuT1fqTr72Sx+SSxeKR0fWRz/GPz/OP'.
     1025            'rr+OyeqMy+6Myu2LyeyKxueJudSGw+SGorGDvt+Cvd6CvN2Aud'.
     1026            'p+uNd+t9Z9tdV8tdR8tNN6sc94r813rct2q8h0qcZ0qMVzp8Rx'.
     1027            'o8Bwor5tn7ptnrptnrlsnbhqmbRpmbNpi51ol7Flkqtkkqtkka'.
     1028            'pjj6hijaRhjaZgi6NfiqJfiaFdh55bhJtag5pZgphYgJZYf5VX'.
     1029            'cn9Ve5FSeI1RdopRdYlQdYlPc4dPcoZPcoVNcINLboBLbH9GZn'.
     1030            'hGZXdFZHZEY3RDYnJCXW4/W2s/WWg+Wmo7VmU7VGM7U2E6VGM6'.
     1031            'VGI5UV82T1wGxheQAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHU'.
     1032            'gAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElNRQfTAwkUJziL'.
     1033            'PvAsAAAATUlEQVR4nGNgQAHsQgqcEJYgG5Oegy+IxSHOxmTiFs'.
     1034            'gFZMprKBnbB8e7AplaFlbOQUl5ICanX0BEWmEhSAFDVGxKYWEh'.
     1035            'xAjusDBuVOMBJO8LrFHRAykAAAAASUVORK5CYII=' ;
     1036
     1037//==========================================================
     1038// File: bxs_darkgray.png
     1039//==========================================================
     1040        $this->imgdata_xsmall[14][0]= 574 ;
     1041        $this->imgdata_xsmall[14][1]=
     1042            'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABm'.
     1043            'JLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsRAAALEQF/ZF+RAAAB'.
     1044            'iElEQVR42k3QPU8TYRwA8P//ebkXrgdIColXRAOEkJqbaExMut'.
     1045            'DBhE1GNjYHPg+DG6ODiU6QOLjVxITBcFKBYCstlAC2Bz17fe76'.
     1046            'vLD6+wg/1FpTRFR5lpaub/u1eGBGaAT4HneD4OlXx7avtDYUjT'.
     1047            'HQabd2Ti8e3vVSKzxrtHS32wIpFVldno22Nqvvg2Bhl0gp/aNm'.
     1048            'vJ3qqXAtLIva+ks1H0wqlSXi4+d6+OFTfRsAfHJx2d1od24rZP'.
     1049            'xP2HzopINr1mkesX7ccojqif0v9crxWXODZTno3+dNGA7uWLsd'.
     1050            'mUYU4fHJCViMG9umLBmM4L6fagZGg9QKfjZ+Qfy3C3G/B3mugF'.
     1051            'IHHNcDf64E3KJALApk2p8CSolUUqLjFkyxOGMsTtFyJ+Wz57NQ'.
     1052            '8DghS4sLB0svioeZZo7nPhFoUKZDIVFbglkTTnl5/rC8snjAkJ'.
     1053            'Bk/XV5LxHC/v7tR8jzTFPbg8LENK9WX0Vv31T2AEmCSmlKCCoh'.
     1054            'ROnP1U1tPFYjJBRcbtzSf+GPsFTAQBq1n4AAAABKdEVYdHNpZ2'.
     1055            '5hdHVyZQBiYzYyMDIyNjgwYThjODMyMmUxNjk0NWUzZjljOGFh'.
     1056            'N2VmZWFhMjA4OTE2ZjkwOTdhZWE1MzYyMjk0MWRkM2I5EqaPDA'.
     1057            'AAAABJRU5ErkJggg==' ;
    10581058    }
    10591059}
  • trunk/client/modules/Elezioni/grafici/imgdata_bevels.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        IMGDATA_BEVELS.INC
    4 // Description: Base64 encoded images for round bevels
    5 // Created:     2003-03-20
    6 // Ver:         $Id: imgdata_bevels.inc.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        IMGDATA_BEVELS.INC
     4// Description: Base64 encoded images for round bevels
     5// Created:     2003-03-20
     6// Ver:         $Id: imgdata_bevels.inc.php 860 2007-03-23 19:16:19Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    1212    protected $name = 'Round Bevels';
    1313    protected $an = array(MARK_IMG_BEVEL => 'imgdata');
    14 
     14   
    1515    protected $colors = array('green','purple','orange','red','yellow');
    1616    protected $index  = array('green'=>1,'purple'=>4,'orange'=>2,'red'=>0,'yellow'=>3);
     
    1919    protected $imgdata ;
    2020
    21     function __construct() {
    22         //==========================================================
    23         // File: bullets_balls_red_013.png
    24         //==========================================================
    25         $this->imgdata[0][0]= 337 ;
    26         $this->imgdata[0][1]=
    27      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
    28      'BMVEX////////27t/f3+LFwcmNxMuxm62DmqKth1VpZmIWg6fv'.
    29      'HCa7K0BwMEytCjFnIyUlEBg9vhQvAAAAAXRSTlMAQObYZgAAAA'.
    30      'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
    31      'RQfTAxcBNhk+pYJVAAAAl0lEQVR4nE2Q2xLDIAgFHUWBKJf//9'.
    32      'oekmbafVDZARRbK/pYTKP9WNcNv64zzUdd9BjmrgnsVXRNSzO3'.
    33      'CJ5ahdhy0XKQkxld1kxb45j7dp0x2lBNOyVgQpMaoadX7Hs7zr'.
    34      'P1yKj47DKBnKaBKiSAkNss7O6PkMx6kIgYXISQJpcZCqdY6KR+'.
    35      'J1PkS5Xob/h7MNz8x6D3fz5DKQjpkZOBYAAAAABJRU5ErkJggg'.
    36      '==' ;
     21    function ImgData_Bevels() {
     22//==========================================================
     23// File: bullets_balls_red_013.png
     24//==========================================================
     25        $this->imgdata[0][0]= 337 ;
     26        $this->imgdata[0][1]=
     27            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
     28            'BMVEX////////27t/f3+LFwcmNxMuxm62DmqKth1VpZmIWg6fv'.
     29            'HCa7K0BwMEytCjFnIyUlEBg9vhQvAAAAAXRSTlMAQObYZgAAAA'.
     30            'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
     31            'RQfTAxcBNhk+pYJVAAAAl0lEQVR4nE2Q2xLDIAgFHUWBKJf//9'.
     32            'oekmbafVDZARRbK/pYTKP9WNcNv64zzUdd9BjmrgnsVXRNSzO3'.
     33            'CJ5ahdhy0XKQkxld1kxb45j7dp0x2lBNOyVgQpMaoadX7Hs7zr'.
     34            'P1yKj47DKBnKaBKiSAkNss7O6PkMx6kIgYXISQJpcZCqdY6KR+'.
     35            'J1PkS5Xob/h7MNz8x6D3fz5DKQjpkZOBYAAAAABJRU5ErkJggg'.
     36            '==' ;
    3737
    38         //==========================================================
    39         // File: bullets_balls_green_013.png
    40         //==========================================================
    41         $this->imgdata[1][0]= 344 ;
    42         $this->imgdata[1][1]=
    43      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
    44      'BMVEX////////27t/e3+K3vriUub/Dm18j4xc3ob10k0ItqQlU'.
    45      'e5JBmwpxY1ENaKBgUh0iHgwsSre9AAAAAXRSTlMAQObYZgAAAA'.
    46      'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
    47      'RQfTAxcBNTfJXtxZAAAAnklEQVR4nE2QWY4EMQhDUVhSIRC4/2'.
    48      'kbaqLp9p+f2AxAayAzDfiK9znPORuvH0x8Ss9z6I9sHp6tcxE9'.
    49      'nLmWmebmt5F5p2AR0+C9AWpLBjXRaZsCAT3SqklVp0YkAWaGtd'.
    50      'c5Z41/STYpPzW7BjyiRrwkVmQto/Cw9tNEMvsgcekyCyFPboIu'.
    51      'IsuXiKffYB4NK4r/h6d4g9HPPwCR7i8+GscIiiaonUAAAAAASU'.
    52      'VORK5CYII=' ;
     38//==========================================================
     39// File: bullets_balls_green_013.png
     40//==========================================================
     41        $this->imgdata[1][0]= 344 ;
     42        $this->imgdata[1][1]=
     43            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
     44            'BMVEX////////27t/e3+K3vriUub/Dm18j4xc3ob10k0ItqQlU'.
     45            'e5JBmwpxY1ENaKBgUh0iHgwsSre9AAAAAXRSTlMAQObYZgAAAA'.
     46            'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
     47            'RQfTAxcBNTfJXtxZAAAAnklEQVR4nE2QWY4EMQhDUVhSIRC4/2'.
     48            'kbaqLp9p+f2AxAayAzDfiK9znPORuvH0x8Ss9z6I9sHp6tcxE9'.
     49            'nLmWmebmt5F5p2AR0+C9AWpLBjXRaZsCAT3SqklVp0YkAWaGtd'.
     50            'c5Z41/STYpPzW7BjyiRrwkVmQto/Cw9tNEMvsgcekyCyFPboIu'.
     51            'IsuXiKffYB4NK4r/h6d4g9HPPwCR7i8+GscIiiaonUAAAAAASU'.
     52            'VORK5CYII=' ;
    5353
    54         //==========================================================
    55         // File: bullets_balls_oy_035.png
    56         //==========================================================
    57         $this->imgdata[2][0]= 341 ;
    58         $this->imgdata[2][1]=
    59      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
    60      'BMVEX////////27t/f3+K5tbqNwcjnkjXjbxR2i5anfEoNkbis'.
    61      'PBxpU0sZbZejKgdqIRIlERIwYtkYAAAAAXRSTlMAQObYZgAAAA'.
    62      'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
    63      'RQfTAxcBNgK0wEu5AAAAm0lEQVR4nE3QVxIEIQgEUErAgTHA/U'.
    64      '+7zbipf9RXgoGo0liMmX6RdSPLPtZM9F4LuuSIaZtZWffiU6Iz'.
    65      'Y8SOMF0NogBj30ioGRGLZgiPvce1TbIRz6oBQEbOFGK0rIoxrn'.
    66      '5hDomMA1cfGRCaRVhjS3gkzheM+4HtnlkXcvdZhWG4qZawewe6'.
    67      '9Jnz/TKLB/ML6HUepn//QczazuwFO/0Ivpolhi4AAAAASUVORK'.
    68      '5CYII=' ;
     54//==========================================================
     55// File: bullets_balls_oy_035.png
     56//==========================================================
     57        $this->imgdata[2][0]= 341 ;
     58        $this->imgdata[2][1]=
     59            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
     60            'BMVEX////////27t/f3+K5tbqNwcjnkjXjbxR2i5anfEoNkbis'.
     61            'PBxpU0sZbZejKgdqIRIlERIwYtkYAAAAAXRSTlMAQObYZgAAAA'.
     62            'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
     63            'RQfTAxcBNgK0wEu5AAAAm0lEQVR4nE3QVxIEIQgEUErAgTHA/U'.
     64            '+7zbipf9RXgoGo0liMmX6RdSPLPtZM9F4LuuSIaZtZWffiU6Iz'.
     65            'Y8SOMF0NogBj30ioGRGLZgiPvce1TbIRz6oBQEbOFGK0rIoxrn'.
     66            '5hDomMA1cfGRCaRVhjS3gkzheM+4HtnlkXcvdZhWG4qZawewe6'.
     67            '9Jnz/TKLB/ML6HUepn//QczazuwFO/0Ivpolhi4AAAAASUVORK'.
     68            '5CYII=' ;
    6969
    70         //==========================================================
    71         // File: bullets_balls_oy_036.png
    72         //==========================================================
    73         $this->imgdata[3][0]= 340 ;
    74         $this->imgdata[3][1]=
    75      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
    76      'BMVEX////////27t/e3+LO3hfYzz65ubiNwci6uQ12ipadgVGa'.
    77      'fwsNkbhnVkcaZ5dwSA8lFg7CEepmAAAAAXRSTlMAQObYZgAAAA'.
    78      'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'.
    79      'RQfTAxcCBySi1nevAAAAjElEQVR4nFXPWw7EIAgFUNMoCMhj/6'.
    80      'staKczc/2RkwjS2glQ+w3YytgXCXCZpRo8gJdGxZadJws13CUP'.
    81      '4SZI4MYiUxypeiGGw1XShVBTNN9kLXP2GRrZPFvKgd7z/sqGGV'.
    82      '7C7r7r3l09alYN3iA8Yn+ImdVrNoEeSRqJPAaHfhZzLYwXstdZ'.
    83      'rP3n2bvdAI4INwtihiwAAAAASUVORK5CYII=' ;
     70//==========================================================
     71// File: bullets_balls_oy_036.png
     72//==========================================================
     73        $this->imgdata[3][0]= 340 ;
     74        $this->imgdata[3][1]=
     75            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
     76            'BMVEX////////27t/e3+LO3hfYzz65ubiNwci6uQ12ipadgVGa'.
     77            'fwsNkbhnVkcaZ5dwSA8lFg7CEepmAAAAAXRSTlMAQObYZgAAAA'.
     78            'FiS0dEAIgFHUgAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAHdElN'.
     79            'RQfTAxcCBySi1nevAAAAjElEQVR4nFXPWw7EIAgFUNMoCMhj/6'.
     80            'staKczc/2RkwjS2glQ+w3YytgXCXCZpRo8gJdGxZadJws13CUP'.
     81            '4SZI4MYiUxypeiGGw1XShVBTNN9kLXP2GRrZPFvKgd7z/sqGGV'.
     82            '7C7r7r3l09alYN3iA8Yn+ImdVrNoEeSRqJPAaHfhZzLYwXstdZ'.
     83            'rP3n2bvdAI4INwtihiwAAAAASUVORK5CYII=' ;
    8484
    85         //==========================================================
    86         // File: bullets_balls_pp_019.png
    87         //==========================================================
    88         $this->imgdata[4][0]= 334 ;
    89         $this->imgdata[4][1]=
    90      'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
    91      'BMVEX////+/v7i4eO/w8eHxcvKroNVormtfkjrMN2BeXQrepPc'.
    92      'Esy4IL+OFaR7F25LHF8mFRh5XXtUAAAAAXRSTlMAQObYZgAAAA'.
    93      'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
    94      'RQfTAxcBNgkjEpIxAAAAlElEQVR4nE2QAQ7FIAhDDTAVndL7n3'.
    95      'ZV/7JfEwMvFIWUlkTMVNInbVv5ZeJqG7Smh2QTBwJBpsdizAZP'.
    96      '5NyW0awhK8kYodnZxS6ECvPRp2sI+y7PBv1mN02KH7h77QCJ8D'.
    97      '4VvY5NUgEmCwj6ZMzHtJRgRSXwC1gfcqJJH0GBnSnK1kUQ72DY'.
    98      'CPBv+MCS/e0jib77eQAJxwiEWm7hFwAAAABJRU5ErkJggg==' ;
     85//==========================================================
     86// File: bullets_balls_pp_019.png
     87//==========================================================
     88        $this->imgdata[4][0]= 334 ;
     89        $this->imgdata[4][1]=
     90            'iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAMAAAAMs7fIAAAAM1'.
     91            'BMVEX////+/v7i4eO/w8eHxcvKroNVormtfkjrMN2BeXQrepPc'.
     92            'Esy4IL+OFaR7F25LHF8mFRh5XXtUAAAAAXRSTlMAQObYZgAAAA'.
     93            'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
     94            'RQfTAxcBNgkjEpIxAAAAlElEQVR4nE2QAQ7FIAhDDTAVndL7n3'.
     95            'ZV/7JfEwMvFIWUlkTMVNInbVv5ZeJqG7Smh2QTBwJBpsdizAZP'.
     96            '5NyW0awhK8kYodnZxS6ECvPRp2sI+y7PBv1mN02KH7h77QCJ8D'.
     97            '4VvY5NUgEmCwj6ZMzHtJRgRSXwC1gfcqJJH0GBnSnK1kUQ72DY'.
     98            'CPBv+MCS/e0jib77eQAJxwiEWm7hFwAAAABJRU5ErkJggg==' ;
    9999
    100100    }
  • trunk/client/modules/Elezioni/grafici/imgdata_diamonds.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        IMGDATA_DIAMONDS.INC
    4 // Description: Base64 encoded images for diamonds
    5 // Created:     2003-03-20
    6 // Ver:         $Id: imgdata_diamonds.inc.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        IMGDATA_DIAMONDS.INC
     4// Description: Base64 encoded images for diamonds
     5// Created:     2003-03-20
     6// Ver:         $Id: imgdata_diamonds.inc.php 860 2007-03-23 19:16:19Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    1212    protected $name = 'Diamonds';
    1313    protected $an = array(MARK_IMG_DIAMOND =>'imgdata');
    14     protected $colors = array('lightblue','darkblue','gray',
    15    'blue','pink','purple','red','yellow');
    16     protected $index  = array('lightblue' =>7,'darkblue'=>2,'gray'=>6,
    17    'blue'=>4,'pink'=>1,'purple'=>5,'red'=>0,'yellow'=>3);
     14    protected $colors = array('lightblue','darkblue','gray', 
     15                        'blue','pink','purple','red','yellow');
     16    protected $index  = array('lightblue' =>7,'darkblue'=>2,'gray'=>6, 
     17                        'blue'=>4,'pink'=>1,'purple'=>5,'red'=>0,'yellow'=>3);
    1818
    1919    protected $maxidx = 7 ;
    2020    protected $imgdata ;
    2121
    22     function __construct() {
    23         //==========================================================
    24         // File: diam_red.png
    25         //==========================================================
    26         $this->imgdata[0][0]= 668 ;
    27         $this->imgdata[0][1]=
    28      'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'.
    29      'BMVEX///////+cAAD/AADOAABjAABrAADWGBjOCAj/CAj/GBj/'.
    30      'EBCcCAiMOTl7KSl7ISFzGBilGBjOEBBrCAjv5+eMQkK1QkKtMT'.
    31      'GtKSnWKSn/KSlzEBCcEBDexsb/tbXOe3ucWlqcUlKUSkr/e3vn'.
    32      'a2u9UlL/a2uEMTHeUlLeSkqtOTn/UlL/SkrWOTn/QkL/OTmlIS'.
    33      'H/MTH/ISH39/f/9/f35+fezs7/5+fvzs7WtbXOra3nvb3/zs7G'.
    34      'nJzvtbXGlJTepaW9jIy1hITWlJS1e3uta2ulY2P/lJTnhITne3'.
    35      'vGY2O9Wlr/c3PeY2O1Skr/Y2P/WlreQkLWISGlEBCglEUaAAAA'.
    36      'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'.
    37      'sSAdLdfvwAAAAHdElNRQfTAwsWEw5WI4qnAAABGUlEQVR4nHXQ'.
    38      '1XLDMBAFUKUCM1NiO8zcpIxpp8z0//9SWY7b2LHv6EU6s1qtAN'.
    39      'iMBAojLPkigpJvogKC4pxDuQipjanlICXof1RQDkYEF21mKIfg'.
    40      '/GGKtjAmOKt9oSyuCU7OhyiDCQnjowGfRnooCJIkiWJvv8NxnG'.
    41      'nyNAwFcekvZpPP3mu7Vrp8fOq8DYbTyjdnAvBj7Jbd7nP95urs'.
    42      '+MC2D6unF+Cu0VJULQBAlsOQuueN3Hrp2nGUvqppemBZ0aU7Se'.
    43      'SXvYZFMKaLJn7MH3btJmZEMEmGSOreqy0SI/4ffo3uiUOYEACy'.
    44      'OFopmNWlP5uZd9uPWmUoxvK9ilO9NtBo6mS7KkZD0fOJYqgGBU'.
    45      'S/T7OKCAA9tfsFOicXcbxt29cAAAAASUVORK5CYII=' ;
     22    function ImgData_Diamonds() {
     23//==========================================================
     24// File: diam_red.png
     25//==========================================================
     26        $this->imgdata[0][0]= 668 ;
     27        $this->imgdata[0][1]=
     28            'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'.
     29            'BMVEX///////+cAAD/AADOAABjAABrAADWGBjOCAj/CAj/GBj/'.
     30            'EBCcCAiMOTl7KSl7ISFzGBilGBjOEBBrCAjv5+eMQkK1QkKtMT'.
     31            'GtKSnWKSn/KSlzEBCcEBDexsb/tbXOe3ucWlqcUlKUSkr/e3vn'.
     32            'a2u9UlL/a2uEMTHeUlLeSkqtOTn/UlL/SkrWOTn/QkL/OTmlIS'.
     33            'H/MTH/ISH39/f/9/f35+fezs7/5+fvzs7WtbXOra3nvb3/zs7G'.
     34            'nJzvtbXGlJTepaW9jIy1hITWlJS1e3uta2ulY2P/lJTnhITne3'.
     35            'vGY2O9Wlr/c3PeY2O1Skr/Y2P/WlreQkLWISGlEBCglEUaAAAA'.
     36            'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'.
     37            'sSAdLdfvwAAAAHdElNRQfTAwsWEw5WI4qnAAABGUlEQVR4nHXQ'.
     38            '1XLDMBAFUKUCM1NiO8zcpIxpp8z0//9SWY7b2LHv6EU6s1qtAN'.
     39            'iMBAojLPkigpJvogKC4pxDuQipjanlICXof1RQDkYEF21mKIfg'.
     40            '/GGKtjAmOKt9oSyuCU7OhyiDCQnjowGfRnooCJIkiWJvv8NxnG'.
     41            'nyNAwFcekvZpPP3mu7Vrp8fOq8DYbTyjdnAvBj7Jbd7nP95urs'.
     42            '+MC2D6unF+Cu0VJULQBAlsOQuueN3Hrp2nGUvqppemBZ0aU7Se'.
     43            'SXvYZFMKaLJn7MH3btJmZEMEmGSOreqy0SI/4ffo3uiUOYEACy'.
     44            'OFopmNWlP5uZd9uPWmUoxvK9ilO9NtBo6mS7KkZD0fOJYqgGBU'.
     45            'S/T7OKCAA9tfsFOicXcbxt29cAAAAASUVORK5CYII=' ;
    4646
    47         //==========================================================
    48         // File: diam_pink.png
    49         //==========================================================
    50         $this->imgdata[1][0]= 262 ;
    51         $this->imgdata[1][1]=
    52      'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
    53      'BMVEX///+AgID/M5n/Zpn/zMz/mZn1xELhAAAAAXRSTlMAQObY'.
    54      'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
    55      'AHdElNRQfTAwsWEi3tX8qUAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
    56      'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
    57      '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
    58      'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
    59      '==' ;
     47//==========================================================
     48// File: diam_pink.png
     49//==========================================================
     50        $this->imgdata[1][0]= 262 ;
     51        $this->imgdata[1][1]=
     52            'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
     53            'BMVEX///+AgID/M5n/Zpn/zMz/mZn1xELhAAAAAXRSTlMAQObY'.
     54            'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
     55            'AHdElNRQfTAwsWEi3tX8qUAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
     56            'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
     57            '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
     58            'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
     59            '==' ;
    6060
    61         //==========================================================
    62         // File: diam_blue.png
    63         //==========================================================
    64         $this->imgdata[2][0]= 662 ;
    65         $this->imgdata[2][1]=
    66      'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA+V'.
    67      'BMVEX///+AgIAAAJwAAP8AAM4AAGMAAGsQEP8YGHMQEHMYGP8Q'.
    68      'EKUICJwICM5KSpQxMYQpKXsYGNYQEM4ICGsICP97e85aWpw5OY'.
    69      'xSUv85ObVCQt4xMa0pKa0hIaUpKf+9vd6EhLVra+dzc/9SUr1r'.
    70      'a/9aWt5SUt5CQrVaWv9KSv8hIXs5Of8xMf8pKdYhIdYYGKUhIf'.
    71      '/Ozs739//v7/fn5+/v7//n5/fW1ufOzufOzu/W1v+trc69veel'.
    72      'pc6trd6UlMa9vf+MjL21tfe1tf+UlNZzc61ra6Wlpf+EhOeMjP'.
    73      '9ra8ZSUpyEhP9CQoxKSrVCQv85Od4xMdYQENZnJhlWAAAAAXRS'.
    74      'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'.
    75      'LdfvwAAAAHdElNRQfTAwsWEx3Snct5AAABFklEQVR4nHXR5XbD'.
    76      'IBgGYM6AuHsaqbvOfeuknev9X8xISbplSd5/8JyXwwcA/I0AKm'.
    77      'PFchVBdvKNKggKQx2VIoRwMZihMiQE49YUlWBCcPL0hYq4ITh+'.
    78      'qKECUoLDZWqoQNA766F/mJHlHXblPJJNiyURhM5eU9cNw5BlmS'.
    79      'IrLOLxhzfotF7vwO2j3ez2ap/TmW4AIM7DoN9+tu+vLk6Pdg9O'.
    80      '6ufXjfXLm6pxPACSJIpRFAa+/26DhuK6qjbiON40k0N3skjOvm'.
    81      'NijBmchF5mi+1jhQqDmWyIzPp1hUlrv8On5l+6mMm1tigFNyrt'.
    82      '5R97g+FKKyGKkTNKesXPJTZXOFIrUoKiypcTQVHjK4g8H2dWEQ'.
    83      'B8bvUDLSQXSr41rmEAAAAASUVORK5CYII=' ;
     61//==========================================================
     62// File: diam_blue.png
     63//==========================================================
     64        $this->imgdata[2][0]= 662 ;
     65        $this->imgdata[2][1]=
     66            'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA+V'.
     67            'BMVEX///+AgIAAAJwAAP8AAM4AAGMAAGsQEP8YGHMQEHMYGP8Q'.
     68            'EKUICJwICM5KSpQxMYQpKXsYGNYQEM4ICGsICP97e85aWpw5OY'.
     69            'xSUv85ObVCQt4xMa0pKa0hIaUpKf+9vd6EhLVra+dzc/9SUr1r'.
     70            'a/9aWt5SUt5CQrVaWv9KSv8hIXs5Of8xMf8pKdYhIdYYGKUhIf'.
     71            '/Ozs739//v7/fn5+/v7//n5/fW1ufOzufOzu/W1v+trc69veel'.
     72            'pc6trd6UlMa9vf+MjL21tfe1tf+UlNZzc61ra6Wlpf+EhOeMjP'.
     73            '9ra8ZSUpyEhP9CQoxKSrVCQv85Od4xMdYQENZnJhlWAAAAAXRS'.
     74            'TlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAd'.
     75            'LdfvwAAAAHdElNRQfTAwsWEx3Snct5AAABFklEQVR4nHXR5XbD'.
     76            'IBgGYM6AuHsaqbvOfeuknev9X8xISbplSd5/8JyXwwcA/I0AKm'.
     77            'PFchVBdvKNKggKQx2VIoRwMZihMiQE49YUlWBCcPL0hYq4ITh+'.
     78            'qKECUoLDZWqoQNA766F/mJHlHXblPJJNiyURhM5eU9cNw5BlmS'.
     79            'IrLOLxhzfotF7vwO2j3ez2ap/TmW4AIM7DoN9+tu+vLk6Pdg9O'.
     80            '6ufXjfXLm6pxPACSJIpRFAa+/26DhuK6qjbiON40k0N3skjOvm'.
     81            'NijBmchF5mi+1jhQqDmWyIzPp1hUlrv8On5l+6mMm1tigFNyrt'.
     82            '5R97g+FKKyGKkTNKesXPJTZXOFIrUoKiypcTQVHjK4g8H2dWEQ'.
     83            'B8bvUDLSQXSr41rmEAAAAASUVORK5CYII=' ;
    8484
    85         //==========================================================
    86         // File: diam_yellow.png
    87         //==========================================================
    88         $this->imgdata[3][0]= 262 ;
    89         $this->imgdata[3][1]=
    90      'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
    91      'BMVEX///+AgIBmMwCZZgD/zADMmQD/QLMZAAAAAXRSTlMAQObY'.
    92      'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
    93      'AHdElNRQfTAwsWEwcv/zIDAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
    94      'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
    95      '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
    96      'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
    97      '==' ;
     85//==========================================================
     86// File: diam_yellow.png
     87//==========================================================
     88        $this->imgdata[3][0]= 262 ;
     89        $this->imgdata[3][1]=
     90            'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
     91            'BMVEX///+AgIBmMwCZZgD/zADMmQD/QLMZAAAAAXRSTlMAQObY'.
     92            'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
     93            'AHdElNRQfTAwsWEwcv/zIDAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
     94            'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
     95            '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
     96            'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
     97            '==' ;
    9898
    99         //==========================================================
    100         // File: diam_lightblue.png
    101         //==========================================================
    102         $this->imgdata[4][0]= 671 ;
    103         $this->imgdata[4][1]=
    104      'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/1'.
    105      'BMVEX///+AgIAAnP8A//8Azv8AY/8Aa/8I//8Y1v8Izv8Y//8Q'.
    106      '//8InP8Qzv8Ypf85jP8he/8Yc/8Ia/8pe/8p//8p1v9Ctf8xrf'.
    107      '8prf8QnP8Qc/9CjP+1//97//9r//9S//9K//9C//85//8x//8h'.
    108      '//9r5/9K3v9S3v851v97zv9Svf85rf8hpf/G3v9SnP9anP9KlP'.
    109      '8xhP/n7//v7+f3///n///O//+U//9z//9j//9a//975/9C3v8h'.
    110      '1v+E5/+17/9j3v/O7//n9/+95/+l3v9jxv+U1v8Qpf9avf9Ktf'.
    111      '+Uxv+11v97tf9rrf+cxv+Mvf9jpf+tzv+Etf/O3v/39/8Akkxr'.
    112      'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
    113      'IAAAsSAdLdfvwAAAAHdElNRQfTAwsWEiHk6Ya/AAABGUlEQVR4'.
    114      'nHXQ13KDMBAF0J2o0E01GHDvJa7p3em95/+/JQJMYjDc0Yt0Zr'.
    115      'VaAaxHgtxwbSGPkGQpOIeQ2ORxJiJmNWYZyAhZR0WcgQGhViU0'.
    116      'nEGoedDHGxgRapRPcRpXhOr7XZzCmLjaXk9IIjvkOEmSRLG62+'.
    117      'F5XlEElhA5sW21GvXj6mGlDBfnJ51lr9svnvEKwH1hu2QPbwd3'.
    118      'N9eXVzuL7/Hn29frdKaamgcgy67L3HFG9gDefV+dm5qme4YRXL'.
    119      'oVR374mRqUELZYosf84XAxISFRQuMh4rrH8YxGSP6HX6H97NNQ'.
    120      'KEAaR08qCeuSnx2a8zIPWqUowtKHSRK91rAw0elmVYQFVc8mhq'.
    121      '7p5RD7Ps3IIwA9sfsFxFUX6eZ4Zh4AAAAASUVORK5CYII=' ;
     99//==========================================================
     100// File: diam_lightblue.png
     101//==========================================================
     102        $this->imgdata[4][0]= 671 ;
     103        $this->imgdata[4][1]=
     104            'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/1'.
     105            'BMVEX///+AgIAAnP8A//8Azv8AY/8Aa/8I//8Y1v8Izv8Y//8Q'.
     106            '//8InP8Qzv8Ypf85jP8he/8Yc/8Ia/8pe/8p//8p1v9Ctf8xrf'.
     107            '8prf8QnP8Qc/9CjP+1//97//9r//9S//9K//9C//85//8x//8h'.
     108            '//9r5/9K3v9S3v851v97zv9Svf85rf8hpf/G3v9SnP9anP9KlP'.
     109            '8xhP/n7//v7+f3///n///O//+U//9z//9j//9a//975/9C3v8h'.
     110            '1v+E5/+17/9j3v/O7//n9/+95/+l3v9jxv+U1v8Qpf9avf9Ktf'.
     111            '+Uxv+11v97tf9rrf+cxv+Mvf9jpf+tzv+Etf/O3v/39/8Akkxr'.
     112            'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
     113            'IAAAsSAdLdfvwAAAAHdElNRQfTAwsWEiHk6Ya/AAABGUlEQVR4'.
     114            'nHXQ13KDMBAF0J2o0E01GHDvJa7p3em95/+/JQJMYjDc0Yt0Zr'.
     115            'VaAaxHgtxwbSGPkGQpOIeQ2ORxJiJmNWYZyAhZR0WcgQGhViU0'.
     116            'nEGoedDHGxgRapRPcRpXhOr7XZzCmLjaXk9IIjvkOEmSRLG62+'.
     117            'F5XlEElhA5sW21GvXj6mGlDBfnJ51lr9svnvEKwH1hu2QPbwd3'.
     118            'N9eXVzuL7/Hn29frdKaamgcgy67L3HFG9gDefV+dm5qme4YRXL'.
     119            'oVR374mRqUELZYosf84XAxISFRQuMh4rrH8YxGSP6HX6H97NNQ'.
     120            'KEAaR08qCeuSnx2a8zIPWqUowtKHSRK91rAw0elmVYQFVc8mhq'.
     121            '7p5RD7Ps3IIwA9sfsFxFUX6eZ4Zh4AAAAASUVORK5CYII=' ;
    122122
    123         //==========================================================
    124         // File: diam_purple.png
    125         //==========================================================
    126         $this->imgdata[5][0]= 657 ;
    127         $this->imgdata[5][1]=
    128      'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'.
    129      'BMVEX///////8xAP/OAP+cAP9jAP9rAP+cCP85CP/OEP9SKf/O'.
    130      'CP9CEP9zGP9rCP+lGP/WOf/WIf9KIf9jOf+MQv+EMf97If9zEP'.
    131      '+1Sv+lIf/ne//eUv/na//n5//Oxv/Wzv+chP9zUv97Wv9rQv9a'.
    132      'Mf9KGP/v5/+te/97Kf+9Y/+tOf+tKf+lEP/vtf/WMf/WKf/v7+'.
    133      'f39/+tnP+9rf9rSv9jQv9CGP+ljP+EY//Gtf+tlP+Ma/9zSv/e'.
    134      'zv+UUv+9lP+cWv+lY/+cUv+MOf+EKf+UQv/Opf/OhP/Ga/+1Qv'.
    135      '/Oe/+9Uv/ntf/eWv/eSv/WGP/3zv/vlP/WEP//9/+pL4oHAAAA'.
    136      'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'.
    137      'sSAdLdfvwAAAAHdElNRQfTAwsWEjX+M1LCAAABDklEQVR4nHXQ'.
    138      '1bLDIBAGYFqIEW+ksbr7cXd3ff93OUCamdOE/Mxw882yywLwPz'.
    139      '+gNKotlRFUVnNUQlCxTMRFCKEdE+MgpJaEiIOU4DKaoSIygtb3'.
    140      'FBUQrm3xjPK4JvXjK0A5hFniYSBtIilQVYUm+X0KTVNiYah+2q'.
    141      'ulFb8nUbSovD2+TCavwXQWmnMA6ro+di+uR5cPzfPhVqPV3N1p'.
    142      'n3b3+rimAWAYhP3xnXd7P6oc9vadPsa1wYEs00dFQRAFehlX21'.
    143      '25Sg9NOgwF5jeNTjVL9om0TjDc1lmeCKZ17nFPzhPtSRt6J06R'.
    144      'WKUoeG3MoXRa/wjLHGLodwZcotPqjsYngnWslRBZH91hWTbpD2'.
    145      'EdF1ECWW1SAAAAAElFTkSuQmCC' ;
     123//==========================================================
     124// File: diam_purple.png
     125//==========================================================
     126        $this->imgdata[5][0]= 657 ;
     127        $this->imgdata[5][1]=
     128            'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAMAAAC6CgRnAAAA/F'.
     129            'BMVEX///////8xAP/OAP+cAP9jAP9rAP+cCP85CP/OEP9SKf/O'.
     130            'CP9CEP9zGP9rCP+lGP/WOf/WIf9KIf9jOf+MQv+EMf97If9zEP'.
     131            '+1Sv+lIf/ne//eUv/na//n5//Oxv/Wzv+chP9zUv97Wv9rQv9a'.
     132            'Mf9KGP/v5/+te/97Kf+9Y/+tOf+tKf+lEP/vtf/WMf/WKf/v7+'.
     133            'f39/+tnP+9rf9rSv9jQv9CGP+ljP+EY//Gtf+tlP+Ma/9zSv/e'.
     134            'zv+UUv+9lP+cWv+lY/+cUv+MOf+EKf+UQv/Opf/OhP/Ga/+1Qv'.
     135            '/Oe/+9Uv/ntf/eWv/eSv/WGP/3zv/vlP/WEP//9/+pL4oHAAAA'.
     136            'AXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAA'.
     137            'sSAdLdfvwAAAAHdElNRQfTAwsWEjX+M1LCAAABDklEQVR4nHXQ'.
     138            '1bLDIBAGYFqIEW+ksbr7cXd3ff93OUCamdOE/Mxw882yywLwPz'.
     139            '+gNKotlRFUVnNUQlCxTMRFCKEdE+MgpJaEiIOU4DKaoSIygtb3'.
     140            'FBUQrm3xjPK4JvXjK0A5hFniYSBtIilQVYUm+X0KTVNiYah+2q'.
     141            'ulFb8nUbSovD2+TCavwXQWmnMA6ro+di+uR5cPzfPhVqPV3N1p'.
     142            'n3b3+rimAWAYhP3xnXd7P6oc9vadPsa1wYEs00dFQRAFehlX21'.
     143            '25Sg9NOgwF5jeNTjVL9om0TjDc1lmeCKZ17nFPzhPtSRt6J06R'.
     144            'WKUoeG3MoXRa/wjLHGLodwZcotPqjsYngnWslRBZH91hWTbpD2'.
     145            'EdF1ECWW1SAAAAAElFTkSuQmCC' ;
    146146
    147         //==========================================================
    148         // File: diam_gray.png
    149         //==========================================================
    150         $this->imgdata[6][0]= 262 ;
    151         $this->imgdata[6][1]=
    152      'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
    153      'BMVEX//////wAzMzNmZmbMzMyZmZlq4Qo5AAAAAXRSTlMAQObY'.
    154      'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
    155      'AHdElNRQfTAwsWExZFTxLxAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
    156      'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
    157      '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
    158      'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
    159      '==' ;
     147//==========================================================
     148// File: diam_gray.png
     149//==========================================================
     150        $this->imgdata[6][0]= 262 ;
     151        $this->imgdata[6][1]=
     152            'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
     153            'BMVEX//////wAzMzNmZmbMzMyZmZlq4Qo5AAAAAXRSTlMAQObY'.
     154            'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
     155            'AHdElNRQfTAwsWExZFTxLxAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
     156            'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
     157            '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
     158            'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
     159            '==' ;
    160160
    161         //==========================================================
    162         // File: diam_blgr.png
    163         //==========================================================
    164         $this->imgdata[7][0]= 262 ;
    165         $this->imgdata[7][1]=
    166      'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
    167      'BMVEX///+AgIBmzP9m///M//+Z//8hMmBVAAAAAXRSTlMAQObY'.
    168      'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
    169      'AHdElNRQfTAwsWEwCxm6egAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
    170      'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
    171      '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
    172      'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
    173      '==' ;
     161//==========================================================
     162// File: diam_blgr.png
     163//==========================================================
     164        $this->imgdata[7][0]= 262 ;
     165        $this->imgdata[7][1]=
     166            'iVBORw0KGgoAAAANSUhEUgAAABsAAAAbBAMAAAB/+ulmAAAAEl'.
     167            'BMVEX///+AgIBmzP9m///M//+Z//8hMmBVAAAAAXRSTlMAQObY'.
     168            'ZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAA'.
     169            'AHdElNRQfTAwsWEwCxm6egAAAAbUlEQVR4nFXJwQ3AMAhDUdRm'.
     170            'kKojuCswABf2X6UEEiC+WF+PyDfoGEuvwXogq3Rk1Y6W0tBSG8'.
     171            '6Uwpla6CmJnpoYKRsjjb/Y63vo9kIkLcZCCsbGYGwMRqIzEp1R'.
     172            'OBmFk9HQGA2N0ZEIz5HX+h/jailYpfz4dAAAAABJRU5ErkJggg'.
     173            '==' ;
    174174    }
    175175}
  • trunk/client/modules/Elezioni/grafici/imgdata_pushpins.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File: IMGDATA_PUSHPINS.INC
    4 // Description: Base64 encoded images for pushpins
    5 // Created:  2003-03-20
    6 // Ver:  $Id: imgdata_pushpins.inc.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        IMGDATA_PUSHPINS.INC
     4// Description: Base64 encoded images for pushpins
     5// Created:     2003-03-20
     6// Ver:         $Id: imgdata_pushpins.inc.php 860 2007-03-23 19:16:19Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    1212    protected $name = 'Push pins';
    1313    protected $an = array(MARK_IMG_PUSHPIN => 'imgdata_small',
    14     MARK_IMG_SPUSHPIN => 'imgdata_small',
    15     MARK_IMG_LPUSHPIN => 'imgdata_large');
     14                    MARK_IMG_SPUSHPIN => 'imgdata_small',
     15                    MARK_IMG_LPUSHPIN => 'imgdata_large');
    1616
    1717    protected $colors = array('blue','green','orange','pink','red');
     
    2020    protected $imgdata_large, $imgdata_small ;
    2121
    22     function __construct() {
    23 
    24         // The anchor should be where the needle "hits" the paper
    25         // (bottom left corner)
    26         $this->anchor_x = 0;
    27         $this->anchor_y = 1;
    28 
    29         //==========================================================
    30         // File: ppl_red.png
    31         //==========================================================
    32         $this->imgdata_large[0][0]= 2490 ;
    33         $this->imgdata_large[0][1]=
    34      'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
    35      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
    36      'B3RJTUUH0wMKBh4Ryh89CgAACUdJREFUeJy9mNtTFFcexz+/7p'.
    37      '4Lw1wZJKDGCAwmDAqUySamcCq1ed6k9mn3UfMP7F+1T3nYqn2J'.
    38      'lZdoDEjpbq0KG8EBFBFBEJye6Zmenkv32Ydu5GYiUMmeqq6uqT'.
    39      '6Xz3zP73aOcIKmAQkIFyD3N/jrBPwlKjLQEglVlJKyUjR3u7cc'.
    40      'WLoP3/4dvv03LNrQ8I6x1rFbDML9kOmHvh7IRHU9JKmUSG8vpF'.
    41      'IoXX/TV0AiEM5A5jT0noFMFMJHXUt/d5f9TUAbhtQ3cPFruDog'.
    42      '8klHMnmO0dGYe/myOJGINEwTz3F2higFXgy8PpAkOC+h8hoaCt'.
    43      '4ppHFcQAWSgOQlyI/p+lUjmRxWAwNJd3xca/f34yoFi4tgmjtD'.
    44      'NIFkJ4xcgBCgVqEBFJ9DqcZea/gNAAVEg7AOGYnHe9XoaJd3+X'.
    45      'LISSSwnz6lsbKCZ9sHh4UVdBkwdA6cPwNnIfJPmC3Ctgft3wwQ'.
    46      'QPkvTZJJnbExzfvsM2nMzVG7e5fG48d4lnXwTwEYCjJxuHQBog'.
    47      'BHUfKkgAIIhiGk06hTp/Dm5qS1uYlXLvtWd4gPgIiCrAEcVckT'.
    48      'Ab5p7TaYJrK1hQaEenrwSiVfQdc91P0kSp7Ii89D5ksY/kAkLy'.
    49      'IZXFdXkQjS1YUSEbdcRu168V6+HTUNIKJDRwdE+sBIQmP9Ld59'.
    50      'bEBA3of4F/D+uXb7rGaaCSmXI3pPj64PDaHCYfEqFVSjgWo2D2'.
    51      '73XlJNQTgCyQykIuBWoNKEeh1aLXBPBCggGdBOgxZVSjoajVhH'.
    52      'o5HWlIpq4bCQSgm9vXhK4ZZKh5SUYygp4J1EQVUD9xlU18BJQD'.
    53      'bUbJ5T5XJStyxN9fSI099P3baxV1dRloW2h2ivx/yakg2ot6F1'.
    54      'EkCa4G1D+zVEq5ArKTWM42Q6HUczQV7U66w9e0ZpdRXlOIQ5vF'.
    55      'VHUXILKify4jiEzkOqC3peQMoBQymFlMt4Dx6wUSxSsm2UZXEK'.
    56      'P30QvOUt8/2Sd78CdWwFDTA+gsw3cOlPcPUD+CQB52oQ21RKXM'.
    57      'eRhGXhOg7VoKrx8KuS4ygZhVg3ZI8FGIfwR9BVgAtfwxdXdP3L'.
    58      '86nUR91dXelNXTeWWy10paQHX602YAP1ADASAL7LJvFtMpOCc0'.
    59      'cG3FHuGlz6Gr4YEpnoTCbzsdHRbOzy5RCRiLRMk5rjyOtAimwA'.
    60      'U4U3SurBN/0wnAASBCVDIKpB4kiAB5Ub0/UvO9LpPAMDGfn005'.
    61      'AxPCzxep3Q6iqPLUseBoufCZRsAE6g5g5kKIDfKUj3wnpAG8QB'.
    62      '/Z1OIqANQuI65AtwNScyYXR2XlAXL2YZHzcklRKWl5GVFXFtGx'.
    63      'MoAiV/EQaAGH6BUQNWgQpwFngv+Ca8KUAQEBcwgTJHyMV7679R'.
    64      'XS8YqdSI6u/PMD5ukMtJY3GR2uQkr5aXeWVZOEALmA8WsIAxfL'.
    65      'd0goVLAdCOd+/YpgqeVtBv4yiA++q/RKKXixe7GB8PSyoljcVF'.
    66      'yg8fyubyMpulEk2lyAIfAAvAC+B+oOQFoAt/+0rAejB/EzjNri'.
    67      'vvqNnCd64jxcE39V8spnP+vMbAgDSePKE2NcXm06dslMuUlcID'.
    68      'TuFvqwXMBU8N39bGgRR+ki0Dz4L5DSAe9NGD7zq+6kcN1L6H2b'.
    69      'ao5WWaQHllRTafPmWrVMJUimoAQrBYJFjQwre7B6A8YAi8LCgD'.
    70      '5DVo6/hbb/iHK1KggvFeD3hHziQKEMuiNTNDbXGRTdtmw7Iwla'.
    71      'KGH0oqwbscLOoG46rAY6AOzRhY74PT6QuUKEN4PegXxd/yEDTT'.
    72      'YMWOk+oEaLkuFdNk0zTZwjfkavDUArXWgGXgFb4dEShXhfYqlI'.
    73      'ow3w9rg3B6ED60IOOA5oEYQBrcpG+mj9bg0VG8GMJhVDZLyzAo'.
    74      'VSq8rFYxXXefcjVgG9+uisDrXUCApoKSBcUHMBmHhfcgNwhtD3'.
    75      'q9IG6Lr15b4OUTmPwBJt8JqGuapp05o0mhoHnptLQfPsR+8IBK'.
    76      'uYyNH3yr+B77LHheA3tK1Ta+IrMeTL2C6Xl48TOsNWDDgAz7s5'.
    77      '/r+krP/eddCsbj8fDQ4GBm9MqVvvRXX2VULBayRGRzaYn1SoWa'.
    78      'UjgB4PIB5QK4ZgBXBKaAHxQsrED1H7CRgCUPwgHZDqACmhWwXv'.
    79      '2aDRqGYeRyufS169cvThQKV88PDuYbW1vJ5VRK+5euqxWlPMdX'.
    80      'SRqgreHbZGN3ijfKBXBTAeh2Fdwi2MofshP/dvKwCmKhp4m83Y'.
    81      'vj8Xg4l8tlCoXC0MTExMTFkZE/1m37wvLGRvKRacoD1209E7Fc'.
    82      'pZwYREOQqEJ4z3HskHLsz4AoXykPIBSN0t3dTTQafROoHdumXC'.
    83      '4fjoMiog0ODiauX7+eLxQKV3O53ETdti88nJnJ3rl505ifmWm3'.
    84      'arWSodR8GNbycDoNHy5C5jFold1k8d+DyvELNwg93d18/vnn9P'.
    85      'X1oes6nufx/Plz7t+/fxhQKSWJRCI5NjaWHxkZKdj1+sjSwkJm'.
    86      '+uZN/dZ337VqCwullGUVdZjsgIUC5LqhrUPvCugWuApeApPAzY'.
    87      'PKHWyaphGNRunt7WVwcBARwfM8Ojo6sCzrMKBhGLphGFEF2Wq1'.
    88      '2jc7M5OZ/vHH0MPbt93awkJJmeZsC6ZaMK3DCwvWdNioQUb5B6'.
    89      'AdBR+9SzkAz/NwHIeXL18iIui6TjgcJplMMjY2th8wHo+Hh4aG'.
    90      'MsPDw6fddru7+Phxx51bt/RbN260qwsLpZhlFZsw9QJ+2Pbrga'.
    91      'oJG2FY2oKwuTtVEz9uV34NbqdtbW0xPT1NNBoF4MyZM1y5coWu'.
    92      'rq5dQBHRcrlc4tq1a/l8Pj9RMs38ndu3Ez//9JNXLRZNyuXZJk'.
    93      'xVYKoExQpsK/+IaAuYb7no8zjC/R+A4zisrq7u+53NZjl16tQ+'.
    94      'QIlEIslsNpuPRCJXZ2dnh2/duNFRW1oy07a96MKd575yxRqU1B'.
    95      '5vPMpF5HHa1tYW9+7do7Ozc/eQpZTSQ6FQt1Lq8pMnT/5w7969'.
    96      'nuLcXE1rNufO9fRMhlKpOyvt9qPtVmvb25fFfvvWbrepVCqHwo'.
    97      'xaX19vff/996ZhGC8qlkW9Wt1Onz073fXxxz+6MB+9e9dUjuO+'.
    98      '7ebq9wLdB9hoNCrr6+s/4wf3FCJW3fPmTZhXsNWCprjuW66Dfr'.
    99      '928KAfBhJAEgiJSLuzs7OSTqctoFkqlZRt26j/I+L/AGjPTN4d'.
    100      'Nqn4AAAAAElFTkSuQmCC' ;
    101 
    102         //==========================================================
    103         // File: ppl_orange.png
    104         //==========================================================
    105         $this->imgdata_large[1][0]= 2753 ;
    106         $this->imgdata_large[1][1]=
    107      'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
    108      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
    109      'B3RJTUUH0wMLFQ0VCkHCzQAACk5JREFUeJytmGtzG0d2hp8zNw'.
    110      'AEcRdJ6EJK9FL0CqZUm9jWbkwq3vhDstl8dmLvz8rP2H8Q75ZT'.
    111      'pkRfpLgqsS6WIFEKGYkiSBCDO+banQ8DUpRWEkklXQUUqlCDfv'.
    112      'rp857pgfAOQ4AMOJdg4R/hX96Hf06bvDc5iT07i8yeg8ksiIAI'.
    113      '4TBi/ds9/vivD/njapNHvRBfHXMu410AM+BUoVSF05NQsi1sO4'.
    114      '8402AXwLQTuP31OAZO2aG0MEn14iSlnI1z3LnMk8IZYJyBwjIs'.
    115      '/TWsVIWPJkvMFS4zMfMhUp5BsoCpAAEBLYKaMFGn00jBxnvu02'.
    116      '35+JHmSJEnBpQEcPo38MmCxd/nS9Ry71Ga/g1W9a8gn0GsHkgA'.
    117      '6DGjxkqb5CoO+YxF3A3p+jGjQUzoK+L/V0ADzFMwtSR8eLbAr8'.
    118      'uXOTf9NzhTc0geSLUQcYHgYEH786RMg0zWJHV2Aitv4x/HpHVS'.
    119      'QA2YBqTTGIUq5qkPMWaWkVwPnPtAA/BevmZcjxaaUtHh8pJJGu'.
    120      'DpCB9FvT7A7YT7S3p5vFMNzmWo/O0MSx/Ms3TqI8r59zFTfUQe'.
    121      'I7SBODE3tnfoIxYnNHligwik0zAzDdVpyKbA8sff5YAeMEwgkV'.
    122      'cufQeTJzZoCsaFLKXPTnNpoUTNsSgJmNoGsuNQjIDwYD2HlnZy'.
    123      'k++yxTKXZfKTU8zOpjhneeQYkorSmGERtIlICBKRbLX+y98YN3'.
    124      'ADcNIm+bJD4U3pPnmbEaRgYVRTGBkDSSsmxKfY7ZLuDJA4hdjl'.
    125      'JEgyBB2SJOvQ9RzTpNKoEwNq0CNFvOXR3/HxMgYVPObaz8kPmh'.
    126      'hkEWMatAfRONGGvLizyOE9P8KkpwhPDAgQKJQbELUD0oOIhbbH'.
    127      'JeVTmowxjAgZutB5AoOngA+2DdYrcTyOyYZP9+QpBvI29vwEhb'.
    128      'It042BVQgDy9KTMfkwQG1A9ACCLlgBBGUwxxoc52WDh2ATyEPp'.
    129      '1hoaPvrEBh0Dq5an9OUsl/9hylk5b5c+mowLc4E2Jtw4Eoljyf'.
    130      'ogA/AGEAagNRjGyUxOmEycyVA5EWDBxrmUp3ytLIv/NJP69Goh'.
    131      '+9mFydIvS5PZYkvH1oY/RFtKymlwBFQAgQd+kAA6qSQ8pvn2mp'.
    132      'SkJkuVFHPHBnQMrEt5Sl+e4/Lvp51PF1PF5Xy6WMvOWZXMom8z'.
    133      'OZTQ8+j5sbQiMEwopsCIwRtBGIJSCdzbTGo9NimkDcgdC7Bg49'.
    134      'TG5n4/nfr0Si77WdYp1YzyZEkWPdteaEnB7pPqBTxuIf/VgciE'.
    135      'SgasCPwh+GNIkaNNag1RiPge5pEhMQVjfoLcF+eoXSvbKxedwn'.
    136      'LKzC3KWbOi5/sW5a44/SHFUSgVA7SCzRG0AvA9mPOgFIETgu4n'.
    137      'Ww0wNQWFAqRSL6D2ZQYBdDrQ7R7jXiwgRcvIL02makuTmWtpM/'.
    138      '+BlLMl5vuWzLVEuwH6oYnR1KS8kJINGXMM2YdfRlALoQoQQKeb'.
    139      'bDVwoMdxQMaLCwLo96HZTF5HbrEhmOftianfZisfzueKv7ZmrX'.
    140      'MsjhxKXZGBjzyeEHmSE3oWiggtyVGmE8DTIXTC5NxgAxOAGUM8'.
    141      'fun9mnSSLQ/CxNzOTgJ3LIMgoGwkKBiiMyaVviHVkdCO4FEKNv'.
    142      'LQzWBYHfITPa4UBVM0LR/WB7ARJsdDDTjA6deYFIFUOimJ3d0E'.
    143      'sNdLavYYgBpthqKcjiiJRO8K6CK0CsJTjfQAGaJtD9vQFAxNNQ'.
    144      '1FB0yBAfA8gdMAIagLoCVAen0M00zMOTYShNDtoHs9CAIUoI4E'.
    145      '1IBihCdNhsMhsj6NuV7BCC2IBpBqQaaFOENCCeiEsO1BO4RQgy'.
    146      'I5Hm4k4oIU9MrgZSAdBeTabZz+ODxKQRRBFBJo6IUc51anYRQo'.
    147      'dto+24FNxYCiaWKkQsj00KkO4gxRRkAngJ868M0u3OkkM+hxQA'.
    148      'cQ7YD7GO5XYSsPZybh/TCkFIYY+kWniTW4Q7jXgHvHMhiRpmuW'.
    149      'ca08GZkkZ/nY6TZMNhCnf2CuPoDVJvxpB+q9BHA8Ag1uH+oP4c'.
    150      'YEPCzDwmzSLquShHW/E0YRbG/BjZtw40hAy7aNzJlzRn75E6N0'.
    151      'qiwTzafI7kOU3gWrhzZC2iHcbsPqLlxvJnCt4KC1RYAL3I5hzY'.
    152      'Xv/huePYCtITQMKEnyB4KQvMURuJvw889HGSwUCs7CwkLpo6tX'.
    153      'Ty/+7nel6VLGDn/8N9m+eZuo1UP8iNhLau6b3RfmOsHBGTUYw9'.
    154      'WBNeDrGB4+h/4qNLKwTnLbHj9CJw/6GoIh9Jpvq0HHcayFhYXi'.
    155      'l3/4w9LK8vLKexfma3G/mb/3n1njTivS7tNQaaU1grQDjJ868D'.
    156      'Axx6vmxnBrY9C9IcSbSXbavNjb/S3eN6/0m1JcKBScixcvllZW'.
    157      'Vi6uLC8v12q1v/M8b/HxVjP//YYr32yE4dYWvShO0ogi14xwxq'.
    158      'F4rbnxZ3cMjtpvEEeMvwA0TdOYn5/PffHFF7Vr166tvPeLXyx7'.
    159      'nrd4+/btyg/frFo//Xgncnd67qCn78earQqcmYD3fSi1wPCTSV'.
    160      '3gzqvm9uFOMl5nUAqFQn5paal26dKla57vf7D+6FHph9VV88af'.
    161      'vgq79bo70e3VT2l9A3hYg4UiRALVHTCHSZvYBm4A//6quf8zoG'.
    162      '3bpuM4acMwKr1+//SDe/dK31+/bv90/Xrcq9fduNW6rbVeC+E7'.
    163      'gWdD2DKg4UEpBmPcm10RuScida31ntb62HAigoigDw6Gh0axWH'.
    164      'QWFhZKi4uLZ+I4PrVer2e+u37dXPvqq6hbr7tOp1NXWq89h6/b'.
    165      '8FBB34WGBesdcPrj38lkMkGlUuml0+mu53nR3t4eo9HoSLhMJk'.
    166      'OlUiGdTuN5Hq7rvgA0TdO4cOFC7vPPP6/VarXldqdTu7m2lrv7'.
    167      '7beq++BBO263b/tKrfWSXlbvwJ6CuAtDgTYiaBFMw6BSqfDxxx'.
    168      '+rarWqGo0GN2/eZGtrC6XenAkRoVKpcPXqVWZmZmg0Gty6desF'.
    169      'oIhIOp3Ol8vlmmVZK3fv3Lm09uc/Zwbr653ccPgoNIzvnmn99Z'.
    170      '7W9QG46lAaM5mM2l95GIYUi0VOnz7N7OwsWmsymQzyuse5Q8Mw'.
    171      'DNLpNDMzM5w/f/7A6AGgUkoajYa9urpayOXzUz/fvZutr68Pim'.
    172      'F4/2y1+n2o9Q/ru7uPesPhXnyo4A+vfHp6mmazybNnz9jZ2UFr'.
    173      'TbPZJAhe+8/aS0Mphed5NBoNABqNBqPR6MWBVWstvu/nnj9/Pv'.
    174      'vo0aPq5uZmPBgM/qcwPf39xV/9ajU1M3Nvq9PZaw8GoT50PjdN'.
    175      'k6mpKa5cucL58+eJ45j19XWePHnCzs4OnudhmiaWZRGGIVH05r'.
    176      'yEYYjrumxubrKxsfFyDQJ6NBp1Pc+7C4jWumBaVm+kVL2l1H2l'.
    177      '1G6otS+H6V6z8u3tbVzXpdFooJRicXGRqakptre3uXXr1ltrcT'.
    178      'Qa8ezZszemWAE9rfUdYBOwtVLRbrPZ+48ff+wDvuu6Sr3MB4Dr'.
    179      'uty6desgfa1WC3iRyrNnz4pSSmezWUzTfGtYtNYcdvC/9sMlgP'.
    180      'n5N4cAAAAASUVORK5CYII=' ;
    181 
    182         //==========================================================
    183         // File: ppl_pink.png
    184         //==========================================================
    185         $this->imgdata_large[2][0]= 2779 ;
    186         $this->imgdata_large[2][1]=
    187      'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
    188      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
    189      'B3RJTUUH0wMLFQolY9lkpgAACmhJREFUeJy9mOtzFNl5h5+3b9'.
    190      'Mz0kzPBWmEVtIiWYhIiC0HCDhB8lb8ISk7nzdZ5+/zJ/8BTmpT'.
    191      '660CZLwG1pVFgBkgGIHECEaa+/T9nHzQCCQuRpCNz6mp6g893U'.
    192      '8/c37ve3qEjxiC4OA4n/Lp/EUu/tsMM/+aEWduVBx7WhdkShcY'.
    193      'xUH2zo0Dwod/5N6vf8V//PoGdx8M8EOFPtK9jI8BdHCcMuVSmf'.
    194      'LxHLmSZdm2U8xIbmKETDGDZZnIy4dBbCynyGhphurEDBOlHFnn'.
    195      'qPcyPxTOwDCOccw7w5nlBRZWylI+ny/mZ6rL1dzUZ5/IWGZU3D'.
    196      'ZIOMQDDaJcHDVGWUbJBi9odVr0QoVSPzigIEaZ8vgSS/8wZU3/'.
    197      'k1fylipz5dLM2WlrZqHKaGCKbEbontq3KAKWQyZfZKTgYqc9Bp'.
    198      '2I2PcJ4ogk/UEBQcwipbFZmT13vDBx8fhnE1Ofnp9yJopFyT3X'.
    199      'yANfks0QHSQMDaL37pOxMLIu2UyVkjVKLjyKSeuD8dAYCFkso1'.
    200      'gYMaeWJ40T56cl8yAi/O4FSa2P6kYczIDsgVpAqcDImZPMuAB1'.
    201      'dkLQtcc8a/bwox8IUHAxZVxGZMouSLVYwKuMkD5IxN+JSdsRJB'.
    202      'pexuTVgYYM6EoGmxkmg3/hEhNUMr/hd7dqbOzExMn/GRDAxWZc'.
    203      'j3I8HiXfMjF2FQowKw7pjoN6E/Llw/GBJj8qxVOMlX4ipxc/lY'.
    204      'kl2zBLkmrTcEzMkoNoRLVidLi/9g+Z3I+1xRHX5EcAihxnbPRv'.
    205      'OTU9kZSmpKPy9FTGrLimPZ1H+UiyGaF67w6n7E1DwMngFDxGvc'.
    206      'w70v0xZUby5IxjlIyMssUJrJwVWkXBdbXvSvwEibcSdKCAFI16'.
    207      '4/sc0SRo9cGAGq1DwvQFzV6DVuBiV4zYnlEts6A2TSPcSiXoxo'.
    208      'QqJCEEFMbQ2b69o5qMiOOPqIMQkagu/aSL7waE8101WFShLjk9'.
    209      'yxgEvjRUiyYd+gwAjY2J9VpXfZ/JEXLhDp3OR6U4T97+hEnPwx'.
    210      'tv4HsRjy2tTQSFzQgDUnwSLBQRI+x1ZgcH87Vcv4SF19Kt0ezS'.
    211      '1h9s0Ma25pgr/YJfnLnEysok0+ezjM6EBLldGqKIJYuDRhOQEJ'.
    212      'Oih8X9Q0xmcXNjlCofBJgn78wxVz7L2YWf8tPPz1hnfjbjzfxN'.
    213      'qVwutq2etZXUQSXikcXGIgUiUkJSDIQMJgYGJsaB3c7b1qQ4GZ'.
    214      'xSkdGZIwMeNLfK6uezMnvJK3pLxeVixfvMsyVjSNSO6IV9adPG'.
    215      'AArkEEz8oUkFmBjYGO80qfd6pCWIayD59wIKcsjcKqufn7JO/S'.
    216      'xfyi+5c24pey5rZ09mJRNkiDdT/tzbkBr3SYkpMYpgEaIJSYhI'.
    217      'kSOY1GhilAQk5ntDIojxCZ/kf87Pl85xbuWEnLiUy+cW3NNuJX'.
    218      'MmY5meKf6mT7wZS+THdOjxlG06tIlIOMZxchSxcFFEGAwAGGME'.
    219      'jwyZYSnWL3cXWiIUbUI6hO/vxXuFOV84ycmlBWthNeflTjuzTi'.
    220      'lzJmM5s46Ej0J63/ZoPmoy6PYxtYVNhmfs0mbAND1mmKVMBY1L'.
    221      'mxA1LN7WgXQbCApNhKJHRIM+DQbv7yQGhjnJ5NgFuXBuxpu5mD'.
    222      'udm3LPuY7pmZLUE6L1SIJaIPFuDAqyw9lnwDYv6NFHkWJh4ZDB'.
    223      'wCBFD3uMxsTAwcBAiElpE/KcPg36dIiOvpsRxDCyhmlP2YY9ZU'.
    224      'v8NMb/1id+FGO0DTztkSXLOONUqeITsMkW2zwnJEIDFhYGx+A1'.
    225      'kwK4mASkvKDPc3p0iYhRRwYUhZLUTyV6Eu0t4s1Y4kcx6W6KaM'.
    226      'EZThcXH59RRhGEgIAddnBwNEBKqqpUtWBIF22YDIhJsbEkJqFN'.
    227      'qLtERHs7GnUkwISEQAf0uj30bY39PzbiC6qrDu2cExJ69Nhhhz'.
    228      '59UlIUipCQOnVi4sjG7ubJBy6um0C+he/0iDHQKIQERYyKFLqr'.
    229      'SI/W6kJCnvOcrWSLSquC1/Jw9Ks3R0FQKHr0uMc9bnCDGjX69A'.
    230      'H0XlcJkibN5jOe/alCZStHbjJL9lSMLkXExvCXRiDV6GZEeGeX'.
    231      '3TvvBVQoEjfBL/v0rT75Th7VU5C8gktI6NLlMY+5yU3WWGODDf'.
    232      'r098tHpNFNH7/2lKdXXdz7efLzVaqJIBOCmK8AJUlI6g0aV+9y'.
    233      '9+p7AR3bMQpTBWPy7yeN6fy0jNwewfpvC9Xe+3kFoUuXe9zj5n'.
    234      'BusEGHjh6GIAGawC2FWuvSvbbF1maFylZAsC1ISZADBiVNSJrP'.
    235      'eX73MY//skHP85z5+fnSxQsXj//4n39cmnPn7LbZlsajBmEnBL'.
    236      '1nuEGDG9x4aa5Ldz+h0RCuBqwBv1Wo+7vs9r7n++0MmYeAM+zB'.
    237      '+61EK1QUEnbbtN+9Bh3Hsebn54u//PdfLq9eWl2ZnZ1dSnaSwu'.
    238      'Pin40b9g3doKE0WoNIl65xj3v75njd3BBubQi6ExKmDWkMRKSl'.
    239      'tSbVKQcMao1Go5Ugb0+x53nOyZMnSysrKydXLq1cWlxa/McgCB'.
    240      'Yev3hU+GPrD3I5/q94k3pXYQY58q6B5Bs0HB//neaGx00gyWaz'.
    241      'VCoV7bquCoKAnZ0dfN/f03egLGj0m3XQNE1jdnY2/+WXXy6trq'.
    242      '6uzP3oR5eCIFi4detW5feXL1vr679Let37zVB3/mQytjXJwmSB'.
    243      'wikHp9ShY0RESqObwPrr5oBERKhUKly4cIFqtUq9XufmzZtsbW'.
    244      '2hXvuDwTTNtxZq8TyvsLy8vLS4uLgahOHphw8elL69fNlc++qr'.
    245      'uFOrNXPddm1cczVL5f5P+Lv5MuOJgTGxwYbZpZsCdeAq8M1Bcw'.
    246      'CGYeC6LtVqlRMnTjAyMkKn0yGXyx0N0LZt03Ec1zCMSrfXO37v'.
    247      'zp3S769csb+/ciXt1mrNdHf3ltZ6Lca8ZpJsduhtCdb2gEFJoQ'.
    248      'xADYHuHDS3f32lFEEQUK/XGRkZoVAocP78eZaXl9FaI/Jq25Uk'.
    249      'yWHAYrHozM/PlxYWFibTND32sFbLXrtyxVz76qukXas1M61WTW'.
    250      'm99gx+20TdN9jqtfjP7QzOwwYNp037Zd0DukDnIByA1pqdnR2+'.
    251      '++472u02Z8+eZWJiAsMwDsEBRNGBzYJpmsaJEyfyX3zxxdLS0t'.
    252      'KlVqu1dP3q1cLta9ekU6u1dat1J9b6Sk9kraV1rYXegW7apDYw'.
    253      'kFY6fPc4MNTw88bwfZ/NzU2UUnieRxAEiAiGcXiXfcigiIjruo'.
    254      'VyubxkWdbK7fX1xWvffFMInjzBM82uMT5+p++6V1UUrSe7u03t'.
    255      '+8lezlKt3gHyl0aSJDQaDa5fv876+vo+w6FzDq1BpZRsb2/bly'.
    256      '9f9vL5/Njdu3fzG0+eMJHNxsfn532vXN5NPG/7abPZal6/Hvfe'.
    257      'kroPHfsm98f7AHW9Xo+//vrrlmVZm71+37QNw3JnZ9PK4uJGpV'.
    258      'pt4Dh+vLGhsrmcfv1iHzu01m89HjIdCon2fb8TBMHtvYeRUn50'.
    259      '1Oj4vqp3Ok1f5LYSadfr9dQfDN642P/XeF2DA+SBAuA4jkOhUK'.
    260      'BQKESO43S11p3BYBDt7u4y+CtB/i/q7jp1GMiw2AAAAABJRU5E'.
    261      'rkJggg==' ;
    262 
    263         //==========================================================
    264         // File: ppl_blue.png
    265         //==========================================================
    266         $this->imgdata_large[3][0]= 2284 ;
    267         $this->imgdata_large[3][1]=
    268      'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
    269      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
    270      'B3RJTUUH0wMLFRAiTZAL3gAACHlJREFUeJy9mGtv29YZgJ9zKF'.
    271      'F3y/Q9jh05tuQkarKgbYasde0UBdZgwNou/Vqga/sD9mP2B4a1'.
    272      'BbZ9atFPxb5sqOtmXbI19bqsluPYiR3HN90vFEWRZx/IJI5zqa'.
    273      'x0OwBBSgR5Hj7v+55zSEFXTUgIJyA9C6/9RsjMjAyFIxxJCDc7'.
    274      'iBqKgyZACGg3G2x9+xXf/fG33P3mC9qNKsp1O+1JdkEnQTdgIO'.
    275      'ttCSMUi8gj072MnugllAyB9G8rBGi6RsToJTF6iuRoFi1kHKZf'.
    276      '7fB8Iggj0/Dy23D2dakNTR3JDsXPvzstxmZGRMER1EwHhQAEgE'.
    277      'CLhIkPD6InY9S3djGLJVBtQP1Qb4HDAyoJYQOOZkPx49nhTH9i'.
    278      '7MUBGT7egxkJgd70wZS/CUkoZtA/fRoE1DZ2ACiv52ibReCp4e'.
    279      '7CIEHomxDiuVdGTqUnf/ZeOjR8fpiVXZul5ZrY3bWwbdcLr/dA'.
    280      'AAIpAwQjUWIjQ+g9HZvswiCgBVF9/SI6OSLGzo0i+oLi6+Utbq'.
    281      '+bKEftgwOE/0Ohocf66M+cBjo22U2RQLIHMhmYnvaOpR9S8bSU'.
    282      'UqCURGpRkuMZMm9cIvPGJZLj0yBjT2LprkiSkykx9cuXIhOnUs'.
    283      'm+QNC2XdG02ggBTcvFabsPWwTPpBAChSCgh4kYBpoeplWp47Qs'.
    284      '7EYDt21xINzd5GCAxLExRl89Z+nHjpbKMmjbmkgfDzI0JEW53K'.
    285      'Jaa6NcAOEX8v52uJzsBlAS6u0hcnTIccPRqhWPCUcLD+s1EaUp'.
    286      'HCEhEMCyHNpt9SjgIU12A6iw6xb123vYhaaKjB9tlgMD5X+uBp'.
    287      'zdkpg6azA8EaNQtKlVba+Xez4eCntnJrsDdFsW5nYFpxlFN846'.
    288      'DXe8utkM4mhi+EgQmjYbS2WqexZKk6BpjwJ2YlK5VjeA3pNDiH'.
    289      'YjRWPzPE7tmBo8EWwGhkXx+z3uXL7D3rU97LIF8RBEAl6lK/Uo'.
    290      '6JNM1rZ2aTcr3eUgIQOGTgbdwXMGyRejenLYTvQGbAdRuetSud'.
    291      'OivVuFZgtCEgICghICnZoMhmlVTPR49LCAEkQUhk/B7KXe0MWf'.
    292      'nxj8xVR/cDheK14WZmtVMJSBnlGoN6FmQq0FLfdwJgORKPHRo/'.
    293      'Snzx4G0F/FjJ4KiOdmjPCrrx8bffnMybMv9MQGNG3rzlVqtR1B'.
    294      'sh/CYXCD4Aag1oCW7ZnUOjSp6WFi/QNEB8Y7BfTNjZyCmUvJ0I'.
    295      'XXT47MTp98Ybon9VZCk8cVazfqlNargsY34G7ByAlIjkHd9CCr'.
    296      'LbBdiHViUgiECuDKYCdz8b2cywREdiYZOj8zNnLuzOTzx6ODp+'.
    297      'OaGaqwVzBFqz0Idhz2loE7YEwBLaAJLQcKbW8qjAcBF5Jh0AMP'.
    298      'IOHe6kxgtb3UMO2OxkF//ffK28nQqxfvm3szrtnDVa799Qb/+v'.
    299      'NtsbNSpm3tAv8B+w7Ub0FhAyoBcMPec9oK6raXk48ziQBXQcmC'.
    300      'pT3YqHa0mpEBkTR6wz/Jjo2cy04+fzwxdDquNfQKO7sFUbpu0c'.
    301      'wp3JoAYsA42Bbkl4GCryUNDEM7Avm6Z/CgSYBWG8pNuFuDu1Wo'.
    302      'tjoxKIJGeHIiM/jmK9NnX5ycuJQMtUcqXPvLDTa+qIie4hAJ1U'.
    303      'vdrmO2HaDfB931twJgAn1A4lGT96obPHPLBbhVgUoTHHWo9aAA'.
    304      'JVAKpyKEmQNzWRENAsL18ycKjAFN/9gCNvzLB/390MMmE7pnDi'.
    305      'Bvwt0K5Jv3O+0oB22nJ1Vvjb/UMhOpcKknqN1OiMB2DNHU2G5s'.
    306      'sVndpGJVcZXjX1IAlvw9PmhRQcOFPhsSDkiBrQR1G7brgs0a7D'.
    307      'ag3FK4rguqBXarI4Nt1SJv5gls7TEWtJDRBO2GwnIs8maevFnA'.
    308      'Gx6awLZvzeTBu4kFbLigijC47pscpx0xyDfkvtUEnlarCDtrUC'.
    309      't2HGIhvPHVdVwqjTIrxRU2a5uUrYoP0QZ2gMvACl7+3V/LuKDq'.
    310      'sJuDy597516+CEezIHXv7vcgXQu2l+Bvn8He9Y4AE4kgk5P9DE'.
    311      'R6aFdq5Et5Nit3yTf3m9sBcsAN3+D98c0Fit5JawE25r1zg1Fo'.
    312      '5B8GFD7g+nVYnu8EUEop9XTa0N/9dUbqcphP/rDJzbUClVbpgR'.
    313      'y2fXM3fND95qj75J8AC6BWPINfVSBieK+x+6cS5UCzCLu3oFV9'.
    314      'GqCMx2NGOp2Znpv7aXZudsool3T5J/179sxVlHJ4kGPrP2COBX'.
    315      '/7DmiApWCjxIMXpYNznYuXM+6TAKWUMppOZzLvv//ery5cuDCT'.
    316      'SqVS336bCwr1JfAPB9r+2KAFwJS+OcETzZHz/7v3etl6ipz77X'.
    317      'GAMh6PG+l0OjM3NzczOzs3k0pNnFlbW43+e/GKtMqrblSsF03V'.
    318      'WHcJA0PjIAzvg9JTze2H67g9DjAwOTmZ+uCDD96anZ2dnZiYmF'.
    319      '5dW41++Lvfa1fnr7qllVK9103mXNTnJgPA+YugsvB3HTaEl+Qs'.
    320      'AZ/yeHPPDCiTyaRx5syZbGoilV1dW00szC9oV+avusuLy0Xd0X'.
    321      'MgFkDM+zkYBZEHV8f7wwKu84zmngQoNU0LaZoWUa4K31y5qX/8'.
    322      '4cfyyvwVN5/L10NOKNeg8UmDxoKF5Vfj1xXAgD0JrgAcvBDfel'.
    323      'a4g4AykUgY6XR6emJiIru2ttZXq9S0K19eUcuLy8WQE8o5OAsN'.
    324      'Ggsmpl+NpoL1g9X4UBU+C9xDgEKIwNTUVOqdd955M9mbnJ3/cj'.
    325      '6Vu5aTheXCQXNdVeMzAwJSCGEA2XKpnF1cXIzlFnOVhJPIKdR+'.
    326      'c88ctq4AlVKsrKzw0UcfKcC5uXqzXnNqSzb2pwLxOHP/l7Z/BN'.
    327      'eB01LKt4HTrusKvGr8jB+hGn8MQAkYQMrfw4Nq/MFPtf+rdvDb'.
    328      'k8QL+/5Z4Uepxm7bfwHuTAVUWpWaqAAAAABJRU5ErkJggg==' ;
    329 
    330         //==========================================================
    331         // File: ppl_green.png
    332         //==========================================================
    333         $this->imgdata_large[4][0]= 2854 ;
    334         $this->imgdata_large[4][1]=
    335      'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
    336      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
    337      'B3RJTUUH0wMLFQ4hANhluwAACrNJREFUeJytmF1zE1eagJ+3u9'.
    338      'XdkvUty2AbmLEtEzDBgZ0UpDBOalNTUzU3czl7tct/2n+wt3M/'.
    339      'NVM12SSTQQSyW2TA+QAJQogtYYFtyfrqL3WfvWj5g8AEjzfvhS'.
    340      'SXjk8//Zz3Pf3qCMcJAWxMKlT4kH+jwu/FknnJSUItKFHzCrKA'.
    341      'BggBQx5ziz/wn/yBz3hED4/oaJfSjgVoYjJJgTLTZCjohp7IGT'.
    342      'k5aZ4kb+bRTR30Q7djj8f/kpPMUSCFedRL6W8e8qMQNE6S4xpv'.
    343      'c5HrTPFubiJ3ZnlyOXV59rJYU5Z00h1c3d0brxAiUkScRijisk'.
    344      '6XLTyiN3s8HuAJpniXa/q8/pt8Or+0kF8oXJm5YiydWcIpOrJu'.
    345      'rjOQwd54AQwsMpTJYhPSoYuLQ58An/DnBQSdImXO8avsTPbqpc'.
    346      'lLp67OXDVzMznZLGxSs2qyIRu4at8gKHQEC50kE1icxqCAdxST'.
    347      'xjEA44tqaJlERl8uLWvvnX5PHuQfcCdxh5qq0aX76vj4WgWyXO'.
    348      'QiNgBP8IAaddr08X8+wHFmJSQhBbPAZGoSZSt5wQs6qoNC7UEd'.
    349      '4AEoLIQSCaCCy78Dv8Tiv1hjjW1CRj8XIAgEKqDtt9keboMJZa'.
    350      'vMjuzQVd3Xr9prTJo+GF/jKZea95R25Lxs8jg5qFGiwDnOS0mW'.
    351      'NE0rjNRIt3WbklUCA9mV3Zdz8OBT/JfCQLB0SKYVVjGFYSfx/E'.
    352      '26ow4e6uDujlPFQpE0FU6P8qNTHdXJdEdda0qf0itWBVM3pa/3'.
    353      'ccUlIECJet0cAJoeYk5EZCeS5IwEoerSxccJBwRqFFf38QCTaO'.
    354      'TRVFKJm3NTbtLNSyh2IkhIXsvLCesEGNCWdmwyruSD/z9kUlRc'.
    355      '3bqNlSxhJNJ43p5JITrOEis8Qtr0cXEpU/JT/pmO18n2vb42pU'.
    356      '3JnDnHMBqyPlpnoAaxhr2llv1ZUBqEGlqYwDQMsskMOcMgVL3Y'.
    357      'ZOQTHAcQQiIGjHCwCaiovjrv4hbcpKuJJjIcDHm685RGr4GLCx'.
    358      'YHkAcrLoAoDSLBiAQrMkjqybHJCbxgh+7xAC1MpsgzwRwD3qHL'.
    359      'WyTIBdlAa6u2rHfXaew06PV78ZZjAwleNnkolECoH5i090wOcY'.
    360      '+TgwYzFHiPi1zkOkXexeAMASnVU+LiyiA1wFUuaqggACLizeWw'.
    361      'ycMzyssmVYKkbpGyC5T+OUALk2mKLHKWf+ED/az+YW42d66YL+'.
    362      'aNrmEEzQCFEnKw368EgEvcN1m80eTIQIt0TFOjMJHkzNEBBYPp'.
    363      'sblf8QHzrORO5JaWZ5ZLl6cuJyyxpNPv4PZdoT+GyIxBfI5uUg'.
    364      'eJMCwP2/bIHO1JEudcgUUWOceKNq99mCvnzs5PzRcuTV4y5mRO'.
    365      'SMIjo47z5S7a94oQCNKgJsZwO7D/IDNg3/LLhRNXt4JohBb4aG'.
    366      '82GLdXcf93mQ+Y43r2RHZp+cRy6cqJK4l8MS+tdItaqiYtc0Mm'.
    367      'QpfJARh98HYh9IiXVcaAo58wGb+LBAjbSPgCOcoSa0wzxXtc08'.
    368      '/pv8mfyL+9MLVQvDJ1JVHJV6SZbFI1qtTsB+KlehRtRTGE8Afo'.
    369      'P4DRcAxiEudhAHjjzz+ubgX4oHowakHQOlqzICQwyVPITGVOXi'.
    370      'xfLF6aumzmczl5lHzMff2+fCdPaGttEkXoLQAO9B7C6EugPYby'.
    371      'gVPjGXc5eIbNAJPjGwiAbaAJUQv8wVG7GROkJFpyOqn/ovgLba'.
    372      '44L0+sDaraXb6jzq7aBQWjBOyUoHcaopOgmaA3IRyNDZnA1HjO'.
    373      'HSBkr7eEFDAEngHrQCf+/s2A8cSiSkqcKUeeTjwFy2Jd78t3+L'.
    374      'TR4itIiBLwLQhzkJyB5Cx4HXDaENVQCBAQcRqFIHTRaBIvuYXg'.
    375      'AdsouuNxEL0ZUBHnSQp66R73zYfUtQ6OytKT8RckQAJQoLtgO5'.
    376      'BJgj0D/WfgdyHaAHx8THoUcbGx8ciwhUl3bDEiToURPooeI7pH'.
    377      'MziK9Yd9nU5a6GgKjOH41vsgI4hAcyC5AZkapF+AoYNrjjsuhx'.
    378      'FbtPmeB5ykyQQzTPAWAQWC8S9oAI0QRRuPb9jkmyMZNAOTklvC'.
    379      'GGYZaFkGmkVAh8h4DtKFMIBunG+pB5B5AIkGBDsQ+qBiL20caj'.
    380      'zhJknq5KlgMkLjJHJos4kYEbFJi5vc5eYbATVN02bNWe19+32t'.
    381      'aJWlFm3wbf8Rz5NbDFJdlOFBF/g7cBf0JkrbBb+F6j1DOduEkU'.
    382      '8bWCOiSofPWadBnSZDWmgUkEMGhZCINut8S/0NBtPptFlZrBSu'.
    383      'vnt1+ndnflfIp9OJ/279Ubbbd+lP7KBKPoEBsgnqLph/BRzwdS'.
    384      'LnBUFvHcfdpRsGPAGqwMco6jynz+e0SPKYCHMfLX5VKHwcenR+'.
    385      'Igd1XTcqlUr+xn/cePv91fevzy8sLO2OtrOpWkqL7gXKSAVRdh'.
    386      'ZFEmEXoYkwBNqovoc/3GHH3aUR+jwC1oD/AWrANi4hGwyBzqEG'.
    387      'Vvb77Dgi0eT1VZzJZMxKpVJYXV1dXF1dXVm6sPSvruue3Xzcyj'.
    388      '6/syvDzwj0lNazK6Fj5LFCRZouZpBABj6jXouu3+Np6HNvDHaf'.
    389      'g91t74msbMuOJicnSSaTKKUQEUQEpRSO69But1/dB0VEm5uby9'.
    390      'y4cWNpdXX1+sLCworrume//PuXpeqnVeOban0U1PW2kcx+O9L7'.
    391      'Te9sUB4lWFR9SqNtNGcHx+/RDD2+Am4D94CnQA8OjjlEhMnyJC'.
    392      'srK8zOzu7BiYioMAzZ2Njg9u3brwIqpSSXy2WXl5eXLly4sOo4'.
    393      'zoV6vV6oflrVP/7Tx8Hmw1Zb6ydqmpWp7ha8h4O3gjOhzVANmF'.
    394      'XPMNQWvdDnCXCXuHR+APqH4fbCtm2mp6eZn59H13WJuYXRaKSU'.
    395      'UiSTyVcBdV3XDcOwRaTU7/en19bWCn/79G+JL/76RbhZ22y7u+'.
    396      '6ahl71nPDz/nO17m7wAxlabFOihy4+DvAcqAMbPzZ3OFzX5dmz'.
    397      'Z2iahoiosUUVhiGNRgPHcV4GzGQy5uLiYuH8+fMzo9FoslarJW'.
    398      '9+elP75E+fBJu1zY7qqpqBUW3T/niohnVvy+1zm5aVtp+WE2XT'.
    399      'nrHFzbjh1tYLz3XdPjD4R3BKKba2tqhWq4dzUO3noBPn4H5PKy'.
    400      'LaO++8U7hx48byhQsXVne7u6tf3/v64t3P7mbq9+odt+OuaWi3'.
    401      'PLxbW2ytubjbQCgiMnt6VlaurWgz0zM0m02q1WrUaDSUUuqI56'.
    402      'ivDxE5MCgiYllWtlwuL5mmufLV/a/O/uXPf9Ff1F+80Lv6Yx29'.
    403      '2qHzyZBh3cdvc7gaTZuZkzPh/Py8ACqVSv1/uPZDKXUAGEWRtF'.
    404      'qtxEcffZTL5XLF+2v39fqjeivshA/TpP83JLwzYFBzcA4370Cc'.
    405      'S81nTRBUs9lkOByi1GuOPI4Rh3+26JZlnSkWi781DOPXvV4v3+'.
    406      '/2G0R8kSBxB/jew+tERK+c49m2TblcxrZtXNfl+fPneJ6HZVmU'.
    407      'y2VJJpNyaJ9TSinlOA5bW1u4rntkQA0oAG8D54gb9W3ianxM3A'.
    408      'e/cn73U3Hq1Cm5du2aPjs7a+ztcSIShmE4ajQa6tatWzQajZ+0'.
    409      'fbiKI+It4SvijVUj7kL2qvGfgkskEqTTaZmcnDROnTplJhIJTU'.
    410      'QiwPd9P/Q8T6XTaQzDIAiCfzjP/wFVfszuFqdHXgAAAABJRU5E'.
    411      'rkJggg==' ;
    412 
    413 
    414         //==========================================================
    415         // File: pp_red.png
    416         //==========================================================
    417         $this->imgdata_small[0][0]= 384 ;
    418         $this->imgdata_small[0][1]=
    419      'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
    420      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
    421      'B3RJTUUH0wMJFhouFobZrQAAAQ1JREFUeJyV1dFtwyAQBuD/og'.
    422      'xQdYxa8gRY6hJ0jK6QdohMkTEuE5wUj5ERen05IoLvID7Jkn2G'.
    423      'j8MgTMyMXqRlUQBYq9ydmaL2h1cwqD7l30t+L1iwlbYFRegY7I'.
    424      'SHjkEifGg4ww3aBa/l4+9AhxWWr/dLhEunXUGHq6yGniw3QkOw'.
    425      '3jJ7UBd82n/VVAlAtvsfp98lAj2sAJOhU4AeQ7DC1ubVBODWDJ'.
    426      'TtCsEWa6u5M1NeFs1NzgdtuhHGtj+9Q2IDppQUAL6Cyrlz0gDN'.
    427      'ohSMiJCt861672EiAhEhESG3woJ9V9OKTkwRKbdqz4cHmFLSFg'.
    428      's69+LvAZKdeZ/n89uLnd2g0S+gjd5g8zzjH5Y/eLLi+NPEAAAA'.
    429      'AElFTkSuQmCC' ;
    430 
    431         //==========================================================
    432         // File: pp_orange.png
    433         //==========================================================
    434         $this->imgdata_small[1][0]= 403 ;
    435         $this->imgdata_small[1][1]=
    436      'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
    437      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
    438      'B3RJTUUH0wMJFhwAnApz5AAAASBJREFUeJyN1dFthDAMBuDf7S'.
    439      '3BCm2VCRKpS4QxbhikW6IewzcBqm6Fm6JyH7iEEByCn5AJH38g'.
    440      'BBIRHNUzBAWAGNfe/SrUGv92CtNt309BrfFdMGPjvt9CD8Fyml'.
    441      'ZZaDchRgA/59FDMD18pvNoNyHxMnUmgLmPHoJ+CqqfMaNAH22C'.
    442      'fgqKRwR+GRpxGjXBEiuXDBWQhTK3plxijyWWvtKVS5KNG1xM8I'.
    443      'OBr7geV1WupDqpmTAPKjCqLhxk/z0PImQmjKrAuI6vMXlhFroD'.
    444      'vfdqITXWqg2YMSJEAFcReoag6UXU2DzPG8w5t09YYsAyLWvHrL'.
    445      'HUy6D3XmvMAAhAay8kAJpBosX4vt0G4+4Jam6s6Rz1fgFG0ncA'.
    446      'f3XfOQcA+Acv5IUSdQw9hgAAAABJRU5ErkJggg==' ;
    447 
    448         //==========================================================
    449         // File: pp_pink.png
    450         //==========================================================
    451         $this->imgdata_small[2][0]= 419 ;
    452         $this->imgdata_small[2][1]=
    453      'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
    454      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
    455      'B3RJTUUH0wMJFhsQzvz1RwAAATBJREFUeJyd1MFthDAQheF/oi'.
    456      'gF+JYWQKICkCJRA1vGtrDbxFbhGvY0HVjCLeS2BeTiHFgTB2wg'.
    457      'eRISstCnmcG2qCpbuXf3ADBQzWsPfZfS9y9HsEu4/Fo33Wf4Fx'.
    458      'gxL3a1XkI3wbTNXHLoboVeLFUYDqObYBy+Fw/Uh9DdCmtOwIjF'.
    459      'YvG76CZoOhNGRmpO8zz30CJoOhMAqlDxFzQLppgXj2XaNlP7FF'.
    460      'GLL7ccMYCBgZERgCvXLBrfi2DEclmiKZwFY4tp6sW26bVfnede'.
    461      'e5Hc5dC2bUgrXGKqWrwcXnNYDjmCrcCIiQgDcFYV05kQ8SXmnB'.
    462      'NgPiVN06wrTDGAhz5EWY/FOccTk+cTnHM/YNu2YYllgFxCWuUM'.
    463      'ikzGx+2Gc+4N+CoJW8n+5a2UKm2aBoBvGA6L7wfl8aoAAAAASU'.
    464      'VORK5CYII=' ;
    465 
    466 
    467         //==========================================================
    468         // File: pp_blue.png
    469         //==========================================================
    470         $this->imgdata_small[3][0]= 883 ;
    471         $this->imgdata_small[3][1]=
    472      'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAACi1'.
    473      'BMVEX///8AAAAAADMAAGYAAJkAAMwAAP8zAAAzADMzAGYzAJkz'.
    474      'AMwzAP9mAABmADNmAGZmAJlmAMxmAP+ZAACZADOZAGaZAJmZAM'.
    475      'yZAP/MAADMADPMAGbMAJnMAMzMAP//AAD/ADP/AGb/AJn/AMz/'.
    476      'AP8AMwAAMzMAM2YAM5kAM8wAM/8zMwAzMzMzM2YzM5kzM8wzM/'.
    477      '9mMwBmMzNmM2ZmM5lmM8xmM/+ZMwCZMzOZM2aZM5mZM8yZM//M'.
    478      'MwDMMzPMM2bMM5nMM8zMM///MwD/MzP/M2b/M5n/M8z/M/8AZg'.
    479      'AAZjMAZmYAZpkAZswAZv8zZgAzZjMzZmYzZpkzZswzZv9mZgBm'.
    480      'ZjNmZmZmZplmZsxmZv+ZZgCZZjOZZmaZZpmZZsyZZv/MZgDMZj'.
    481      'PMZmbMZpnMZszMZv//ZgD/ZjP/Zmb/Zpn/Zsz/Zv8AmQAAmTMA'.
    482      'mWYAmZkAmcwAmf8zmQAzmTMzmWYzmZkzmcwzmf9mmQBmmTNmmW'.
    483      'ZmmZlmmcxmmf+ZmQCZmTOZmWaZmZmZmcyZmf/MmQDMmTPMmWbM'.
    484      'mZnMmczMmf//mQD/mTP/mWb/mZn/mcz/mf8AzAAAzDMAzGYAzJ'.
    485      'kAzMwAzP8zzAAzzDMzzGYzzJkzzMwzzP9mzABmzDNmzGZmzJlm'.
    486      'zMxmzP+ZzACZzDOZzGaZzJmZzMyZzP/MzADMzDPMzGbMzJnMzM'.
    487      'zMzP//zAD/zDP/zGb/zJn/zMz/zP8A/wAA/zMA/2YA/5kA/8wA'.
    488      '//8z/wAz/zMz/2Yz/5kz/8wz//9m/wBm/zNm/2Zm/5lm/8xm//'.
    489      '+Z/wCZ/zOZ/2aZ/5mZ/8yZ///M/wDM/zPM/2bM/5nM/8zM////'.
    490      '/wD//zP//2b//5n//8z///9jJVUgAAAAAXRSTlMAQObYZgAAAA'.
    491      'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
    492      'RQfTAwkWGTNerea3AAAAYUlEQVR4nHXNwQ3AIAxDUUfyoROxRZ'.
    493      'icARin0EBTIP3Hp1gBRqSqYo0seqjZpnngojlWBir5+b8o06lM'.
    494      'ha5uFKEpDZulV8l52axhVzqaCdxQp32qVSSwC1wN3fYiw7b76w'.
    495      'bN4SMue4/KbwAAAABJRU5ErkJggg==' ;
    496 
    497         //==========================================================
    498         // File: pp_green.png
    499         //==========================================================
    500         $this->imgdata_small[4][0]= 447 ;
    501         $this->imgdata_small[4][1]=
    502      'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
    503      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
    504      'B3RJTUUH0wMJFhkLdq9eKQAAAUxJREFUeJyN1LFVwzAQxvH/8f'.
    505      'IeDS0FLKABlN6eIwPYAzCHB0gWYI2jj+i1ABUTQN4TRSQ7iiWZ'.
    506      'qxLn9Mt9ydmiqrSq930AYFiu6YdKrf/hP1gYQn6960PxwBaYMG'.
    507      'E9UA3dBFtVQjdBOQmBakLennK0CapRwbZRZ3N0O/IeEsqp3HKL'.
    508      'Smtt5pUZgTPg4gdDud+6xoS97wM2rsxxmRSoTgoVcMZsXJkBho'.
    509      'SmKqCuOuEtls6nmGMFPTUmxBKx/MeyNfQGLoOOiC2ddsxb1Kzv'.
    510      'ZzUqu5IXbGDvBJf+hDisi77qFSuhq7Xpuu66TyJLRGbsXVUPxV'.
    511      'SxsgkzDMt0mKT3/RcjL8C5hHnvJToXY0xYRZ4xnVKsV/S+a8YA'.
    512      'AvCb3s9g13UhYj+TTo93B3fApRV1FVlEAD6H42DjN9/WvzDYuJ'.
    513      'dL5b1/ji+/IX8EGWP4AwRii8PdFHTqAAAAAElFTkSuQmCC' ;
     22    function ImgData_PushPins() {
     23
     24        // The anchor should be where the needle "hits" the paper
     25        // (bottom left corner)
     26        $this->anchor_x = 0;
     27        $this->anchor_y = 1;
     28
     29//==========================================================
     30// File: ppl_red.png
     31//==========================================================
     32        $this->imgdata_large[0][0]= 2490 ;
     33        $this->imgdata_large[0][1]=
     34            'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
     35            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
     36            'B3RJTUUH0wMKBh4Ryh89CgAACUdJREFUeJy9mNtTFFcexz+/7p'.
     37            '4Lw1wZJKDGCAwmDAqUySamcCq1ed6k9mn3UfMP7F+1T3nYqn2J'.
     38            'lZdoDEjpbq0KG8EBFBFBEJye6Zmenkv32Ydu5GYiUMmeqq6uqT'.
     39            '6Xz3zP73aOcIKmAQkIFyD3N/jrBPwlKjLQEglVlJKyUjR3u7cc'.
     40            'WLoP3/4dvv03LNrQ8I6x1rFbDML9kOmHvh7IRHU9JKmUSG8vpF'.
     41            'IoXX/TV0AiEM5A5jT0noFMFMJHXUt/d5f9TUAbhtQ3cPFruDog'.
     42            '8klHMnmO0dGYe/myOJGINEwTz3F2higFXgy8PpAkOC+h8hoaCt'.
     43            '4ppHFcQAWSgOQlyI/p+lUjmRxWAwNJd3xca/f34yoFi4tgmjtD'.
     44            'NIFkJ4xcgBCgVqEBFJ9DqcZea/gNAAVEg7AOGYnHe9XoaJd3+X'.
     45            'LISSSwnz6lsbKCZ9sHh4UVdBkwdA6cPwNnIfJPmC3Ctgft3wwQ'.
     46            'QPkvTZJJnbExzfvsM2nMzVG7e5fG48d4lnXwTwEYCjJxuHQBog'.
     47            'BHUfKkgAIIhiGk06hTp/Dm5qS1uYlXLvtWd4gPgIiCrAEcVckT'.
     48            'Ab5p7TaYJrK1hQaEenrwSiVfQdc91P0kSp7Ii89D5ksY/kAkLy'.
     49            'IZXFdXkQjS1YUSEbdcRu168V6+HTUNIKJDRwdE+sBIQmP9Ld59'.
     50            'bEBA3of4F/D+uXb7rGaaCSmXI3pPj64PDaHCYfEqFVSjgWo2D2'.
     51            '73XlJNQTgCyQykIuBWoNKEeh1aLXBPBCggGdBOgxZVSjoajVhH'.
     52            'o5HWlIpq4bCQSgm9vXhK4ZZKh5SUYygp4J1EQVUD9xlU18BJQD'.
     53            'bUbJ5T5XJStyxN9fSI099P3baxV1dRloW2h2ivx/yakg2ot6F1'.
     54            'EkCa4G1D+zVEq5ArKTWM42Q6HUczQV7U66w9e0ZpdRXlOIQ5vF'.
     55            'VHUXILKify4jiEzkOqC3peQMoBQymFlMt4Dx6wUSxSsm2UZXEK'.
     56            'P30QvOUt8/2Sd78CdWwFDTA+gsw3cOlPcPUD+CQB52oQ21RKXM'.
     57            'eRhGXhOg7VoKrx8KuS4ygZhVg3ZI8FGIfwR9BVgAtfwxdXdP3L'.
     58            '86nUR91dXelNXTeWWy10paQHX602YAP1ADASAL7LJvFtMpOCc0'.
     59            'cG3FHuGlz6Gr4YEpnoTCbzsdHRbOzy5RCRiLRMk5rjyOtAimwA'.
     60            'U4U3SurBN/0wnAASBCVDIKpB4kiAB5Ub0/UvO9LpPAMDGfn005'.
     61            'AxPCzxep3Q6iqPLUseBoufCZRsAE6g5g5kKIDfKUj3wnpAG8QB'.
     62            '/Z1OIqANQuI65AtwNScyYXR2XlAXL2YZHzcklRKWl5GVFXFtGx'.
     63            'MoAiV/EQaAGH6BUQNWgQpwFngv+Ca8KUAQEBcwgTJHyMV7679R'.
     64            'XS8YqdSI6u/PMD5ukMtJY3GR2uQkr5aXeWVZOEALmA8WsIAxfL'.
     65            'd0goVLAdCOd+/YpgqeVtBv4yiA++q/RKKXixe7GB8PSyoljcVF'.
     66            'yg8fyubyMpulEk2lyAIfAAvAC+B+oOQFoAt/+0rAejB/EzjNri'.
     67            'vvqNnCd64jxcE39V8spnP+vMbAgDSePKE2NcXm06dslMuUlcID'.
     68            'TuFvqwXMBU8N39bGgRR+ki0Dz4L5DSAe9NGD7zq+6kcN1L6H2b'.
     69            'ao5WWaQHllRTafPmWrVMJUimoAQrBYJFjQwre7B6A8YAi8LCgD'.
     70            '5DVo6/hbb/iHK1KggvFeD3hHziQKEMuiNTNDbXGRTdtmw7Iwla'.
     71            'KGH0oqwbscLOoG46rAY6AOzRhY74PT6QuUKEN4PegXxd/yEDTT'.
     72            'YMWOk+oEaLkuFdNk0zTZwjfkavDUArXWgGXgFb4dEShXhfYqlI'.
     73            'ow3w9rg3B6ED60IOOA5oEYQBrcpG+mj9bg0VG8GMJhVDZLyzAo'.
     74            'VSq8rFYxXXefcjVgG9+uisDrXUCApoKSBcUHMBmHhfcgNwhtD3'.
     75            'q9IG6Lr15b4OUTmPwBJt8JqGuapp05o0mhoHnptLQfPsR+8IBK'.
     76            'uYyNH3yr+B77LHheA3tK1Ta+IrMeTL2C6Xl48TOsNWDDgAz7s5'.
     77            '/r+krP/eddCsbj8fDQ4GBm9MqVvvRXX2VULBayRGRzaYn1SoWa'.
     78            'UjgB4PIB5QK4ZgBXBKaAHxQsrED1H7CRgCUPwgHZDqACmhWwXv'.
     79            '2aDRqGYeRyufS169cvThQKV88PDuYbW1vJ5VRK+5euqxWlPMdX'.
     80            'SRqgreHbZGN3ijfKBXBTAeh2Fdwi2MofshP/dvKwCmKhp4m83Y'.
     81            'vj8Xg4l8tlCoXC0MTExMTFkZE/1m37wvLGRvKRacoD1209E7Fc'.
     82            'pZwYREOQqEJ4z3HskHLsz4AoXykPIBSN0t3dTTQafROoHdumXC'.
     83            '4fjoMiog0ODiauX7+eLxQKV3O53ETdti88nJnJ3rl505ifmWm3'.
     84            'arWSodR8GNbycDoNHy5C5jFold1k8d+DyvELNwg93d18/vnn9P'.
     85            'X1oes6nufx/Plz7t+/fxhQKSWJRCI5NjaWHxkZKdj1+sjSwkJm'.
     86            '+uZN/dZ337VqCwullGUVdZjsgIUC5LqhrUPvCugWuApeApPAzY'.
     87            'PKHWyaphGNRunt7WVwcBARwfM8Ojo6sCzrMKBhGLphGFEF2Wq1'.
     88            '2jc7M5OZ/vHH0MPbt93awkJJmeZsC6ZaMK3DCwvWdNioQUb5B6'.
     89            'AdBR+9SzkAz/NwHIeXL18iIui6TjgcJplMMjY2th8wHo+Hh4aG'.
     90            'MsPDw6fddru7+Phxx51bt/RbN260qwsLpZhlFZsw9QJ+2Pbrga'.
     91            'oJG2FY2oKwuTtVEz9uV34NbqdtbW0xPT1NNBoF4MyZM1y5coWu'.
     92            'rq5dQBHRcrlc4tq1a/l8Pj9RMs38ndu3Ez//9JNXLRZNyuXZJk'.
     93            'xVYKoExQpsK/+IaAuYb7no8zjC/R+A4zisrq7u+53NZjl16tQ+'.
     94            'QIlEIslsNpuPRCJXZ2dnh2/duNFRW1oy07a96MKd575yxRqU1B'.
     95            '5vPMpF5HHa1tYW9+7do7Ozc/eQpZTSQ6FQt1Lq8pMnT/5w7969'.
     96            'nuLcXE1rNufO9fRMhlKpOyvt9qPtVmvb25fFfvvWbrepVCqHwo'.
     97            'xaX19vff/996ZhGC8qlkW9Wt1Onz073fXxxz+6MB+9e9dUjuO+'.
     98            '7ebq9wLdB9hoNCrr6+s/4wf3FCJW3fPmTZhXsNWCprjuW66Dfr'.
     99            '928KAfBhJAEgiJSLuzs7OSTqctoFkqlZRt26j/I+L/AGjPTN4d'.
     100            'Nqn4AAAAAElFTkSuQmCC' ;
     101
     102//==========================================================
     103// File: ppl_orange.png
     104//==========================================================
     105        $this->imgdata_large[1][0]= 2753 ;
     106        $this->imgdata_large[1][1]=
     107            'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
     108            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
     109            'B3RJTUUH0wMLFQ0VCkHCzQAACk5JREFUeJytmGtzG0d2hp8zNw'.
     110            'AEcRdJ6EJK9FL0CqZUm9jWbkwq3vhDstl8dmLvz8rP2H8Q75ZT'.
     111            'pkRfpLgqsS6WIFEKGYkiSBCDO+banQ8DUpRWEkklXQUUqlCDfv'.
     112            'rp857pgfAOQ4AMOJdg4R/hX96Hf06bvDc5iT07i8yeg8ksiIAI'.
     113            '4TBi/ds9/vivD/njapNHvRBfHXMu410AM+BUoVSF05NQsi1sO4'.
     114            '8402AXwLQTuP31OAZO2aG0MEn14iSlnI1z3LnMk8IZYJyBwjIs'.
     115            '/TWsVIWPJkvMFS4zMfMhUp5BsoCpAAEBLYKaMFGn00jBxnvu02'.
     116            '35+JHmSJEnBpQEcPo38MmCxd/nS9Ry71Ga/g1W9a8gn0GsHkgA'.
     117            '6DGjxkqb5CoO+YxF3A3p+jGjQUzoK+L/V0ADzFMwtSR8eLbAr8'.
     118            'uXOTf9NzhTc0geSLUQcYHgYEH786RMg0zWJHV2Aitv4x/HpHVS'.
     119            'QA2YBqTTGIUq5qkPMWaWkVwPnPtAA/BevmZcjxaaUtHh8pJJGu'.
     120            'DpCB9FvT7A7YT7S3p5vFMNzmWo/O0MSx/Ms3TqI8r59zFTfUQe'.
     121            'I7SBODE3tnfoIxYnNHligwik0zAzDdVpyKbA8sff5YAeMEwgkV'.
     122            'cufQeTJzZoCsaFLKXPTnNpoUTNsSgJmNoGsuNQjIDwYD2HlnZy'.
     123            'k++yxTKXZfKTU8zOpjhneeQYkorSmGERtIlICBKRbLX+y98YN3'.
     124            'ADcNIm+bJD4U3pPnmbEaRgYVRTGBkDSSsmxKfY7ZLuDJA4hdjl'.
     125            'JEgyBB2SJOvQ9RzTpNKoEwNq0CNFvOXR3/HxMgYVPObaz8kPmh'.
     126            'hkEWMatAfRONGGvLizyOE9P8KkpwhPDAgQKJQbELUD0oOIhbbH'.
     127            'JeVTmowxjAgZutB5AoOngA+2DdYrcTyOyYZP9+QpBvI29vwEhb'.
     128            'It042BVQgDy9KTMfkwQG1A9ACCLlgBBGUwxxoc52WDh2ATyEPp'.
     129            '1hoaPvrEBh0Dq5an9OUsl/9hylk5b5c+mowLc4E2Jtw4Eoljyf'.
     130            'ogA/AGEAagNRjGyUxOmEycyVA5EWDBxrmUp3ytLIv/NJP69Goh'.
     131            '+9mFydIvS5PZYkvH1oY/RFtKymlwBFQAgQd+kAA6qSQ8pvn2mp'.
     132            'SkJkuVFHPHBnQMrEt5Sl+e4/Lvp51PF1PF5Xy6WMvOWZXMom8z'.
     133            'OZTQ8+j5sbQiMEwopsCIwRtBGIJSCdzbTGo9NimkDcgdC7Bg49'.
     134            'TG5n4/nfr0Si77WdYp1YzyZEkWPdteaEnB7pPqBTxuIf/VgciE'.
     135            'SgasCPwh+GNIkaNNag1RiPge5pEhMQVjfoLcF+eoXSvbKxedwn'.
     136            'LKzC3KWbOi5/sW5a44/SHFUSgVA7SCzRG0AvA9mPOgFIETgu4n'.
     137            'Ww0wNQWFAqRSL6D2ZQYBdDrQ7R7jXiwgRcvIL02makuTmWtpM/'.
     138            '+BlLMl5vuWzLVEuwH6oYnR1KS8kJINGXMM2YdfRlALoQoQQKeb'.
     139            'bDVwoMdxQMaLCwLo96HZTF5HbrEhmOftianfZisfzueKv7ZmrX'.
     140            'MsjhxKXZGBjzyeEHmSE3oWiggtyVGmE8DTIXTC5NxgAxOAGUM8'.
     141            'fun9mnSSLQ/CxNzOTgJ3LIMgoGwkKBiiMyaVviHVkdCO4FEKNv'.
     142            'LQzWBYHfITPa4UBVM0LR/WB7ARJsdDDTjA6deYFIFUOimJ3d0E'.
     143            'sNdLavYYgBpthqKcjiiJRO8K6CK0CsJTjfQAGaJtD9vQFAxNNQ'.
     144            '1FB0yBAfA8gdMAIagLoCVAen0M00zMOTYShNDtoHs9CAIUoI4E'.
     145            '1IBihCdNhsMhsj6NuV7BCC2IBpBqQaaFOENCCeiEsO1BO4RQgy'.
     146            'I5Hm4k4oIU9MrgZSAdBeTabZz+ODxKQRRBFBJo6IUc51anYRQo'.
     147            'dto+24FNxYCiaWKkQsj00KkO4gxRRkAngJ868M0u3OkkM+hxQA'.
     148            'cQ7YD7GO5XYSsPZybh/TCkFIYY+kWniTW4Q7jXgHvHMhiRpmuW'.
     149            'ca08GZkkZ/nY6TZMNhCnf2CuPoDVJvxpB+q9BHA8Ag1uH+oP4c'.
     150            'YEPCzDwmzSLquShHW/E0YRbG/BjZtw40hAy7aNzJlzRn75E6N0'.
     151            'qiwTzafI7kOU3gWrhzZC2iHcbsPqLlxvJnCt4KC1RYAL3I5hzY'.
     152            'Xv/huePYCtITQMKEnyB4KQvMURuJvw889HGSwUCs7CwkLpo6tX'.
     153            'Ty/+7nel6VLGDn/8N9m+eZuo1UP8iNhLau6b3RfmOsHBGTUYw9'.
     154            'WBNeDrGB4+h/4qNLKwTnLbHj9CJw/6GoIh9Jpvq0HHcayFhYXi'.
     155            'l3/4w9LK8vLKexfma3G/mb/3n1njTivS7tNQaaU1grQDjJ868D'.
     156            'Axx6vmxnBrY9C9IcSbSXbavNjb/S3eN6/0m1JcKBScixcvllZW'.
     157            'Vi6uLC8v12q1v/M8b/HxVjP//YYr32yE4dYWvShO0ogi14xwxq'.
     158            'F4rbnxZ3cMjtpvEEeMvwA0TdOYn5/PffHFF7Vr166tvPeLXyx7'.
     159            'nrd4+/btyg/frFo//Xgncnd67qCn78earQqcmYD3fSi1wPCTSV'.
     160            '3gzqvm9uFOMl5nUAqFQn5paal26dKla57vf7D+6FHph9VV88af'.
     161            'vgq79bo70e3VT2l9A3hYg4UiRALVHTCHSZvYBm4A//6quf8zoG'.
     162            '3bpuM4acMwKr1+//SDe/dK31+/bv90/Xrcq9fduNW6rbVeC+E7'.
     163            'gWdD2DKg4UEpBmPcm10RuScida31ntb62HAigoigDw6Gh0axWH'.
     164            'QWFhZKi4uLZ+I4PrVer2e+u37dXPvqq6hbr7tOp1NXWq89h6/b'.
     165            '8FBB34WGBesdcPrj38lkMkGlUuml0+mu53nR3t4eo9HoSLhMJk'.
     166            'OlUiGdTuN5Hq7rvgA0TdO4cOFC7vPPP6/VarXldqdTu7m2lrv7'.
     167            '7beq++BBO263b/tKrfWSXlbvwJ6CuAtDgTYiaBFMw6BSqfDxxx'.
     168            '+rarWqGo0GN2/eZGtrC6XenAkRoVKpcPXqVWZmZmg0Gty6desF'.
     169            'oIhIOp3Ol8vlmmVZK3fv3Lm09uc/Zwbr653ccPgoNIzvnmn99Z'.
     170            '7W9QG46lAaM5mM2l95GIYUi0VOnz7N7OwsWmsymQzyuse5Q8Mw'.
     171            'DNLpNDMzM5w/f/7A6AGgUkoajYa9urpayOXzUz/fvZutr68Pim'.
     172            'F4/2y1+n2o9Q/ru7uPesPhXnyo4A+vfHp6mmazybNnz9jZ2UFr'.
     173            'TbPZJAhe+8/aS0Mphed5NBoNABqNBqPR6MWBVWstvu/nnj9/Pv'.
     174            'vo0aPq5uZmPBgM/qcwPf39xV/9ajU1M3Nvq9PZaw8GoT50PjdN'.
     175            'k6mpKa5cucL58+eJ45j19XWePHnCzs4OnudhmiaWZRGGIVH05r'.
     176            'yEYYjrumxubrKxsfFyDQJ6NBp1Pc+7C4jWumBaVm+kVL2l1H2l'.
     177            '1G6otS+H6V6z8u3tbVzXpdFooJRicXGRqakptre3uXXr1ltrcT'.
     178            'Qa8ezZszemWAE9rfUdYBOwtVLRbrPZ+48ff+wDvuu6Sr3MB4Dr'.
     179            'uty6desgfa1WC3iRyrNnz4pSSmezWUzTfGtYtNYcdvC/9sMlgP'.
     180            'n5N4cAAAAASUVORK5CYII=' ;
     181
     182//==========================================================
     183// File: ppl_pink.png
     184//==========================================================
     185        $this->imgdata_large[2][0]= 2779 ;
     186        $this->imgdata_large[2][1]=
     187            'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
     188            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
     189            'B3RJTUUH0wMLFQolY9lkpgAACmhJREFUeJy9mOtzFNl5h5+3b9'.
     190            'Mz0kzPBWmEVtIiWYhIiC0HCDhB8lb8ISk7nzdZ5+/zJ/8BTmpT'.
     191            '660CZLwG1pVFgBkgGIHECEaa+/T9nHzQCCQuRpCNz6mp6g893U'.
     192            '8/c37ve3qEjxiC4OA4n/Lp/EUu/tsMM/+aEWduVBx7WhdkShcY'.
     193            'xUH2zo0Dwod/5N6vf8V//PoGdx8M8EOFPtK9jI8BdHCcMuVSmf'.
     194            'LxHLmSZdm2U8xIbmKETDGDZZnIy4dBbCynyGhphurEDBOlHFnn'.
     195            'qPcyPxTOwDCOccw7w5nlBRZWylI+ny/mZ6rL1dzUZ5/IWGZU3D'.
     196            'ZIOMQDDaJcHDVGWUbJBi9odVr0QoVSPzigIEaZ8vgSS/8wZU3/'.
     197            'k1fylipz5dLM2WlrZqHKaGCKbEbontq3KAKWQyZfZKTgYqc9Bp'.
     198            '2I2PcJ4ogk/UEBQcwipbFZmT13vDBx8fhnE1Ofnp9yJopFyT3X'.
     199            'yANfks0QHSQMDaL37pOxMLIu2UyVkjVKLjyKSeuD8dAYCFkso1'.
     200            'gYMaeWJ40T56cl8yAi/O4FSa2P6kYczIDsgVpAqcDImZPMuAB1'.
     201            'dkLQtcc8a/bwox8IUHAxZVxGZMouSLVYwKuMkD5IxN+JSdsRJB'.
     202            'pexuTVgYYM6EoGmxkmg3/hEhNUMr/hd7dqbOzExMn/GRDAxWZc'.
     203            'j3I8HiXfMjF2FQowKw7pjoN6E/Llw/GBJj8qxVOMlX4ipxc/lY'.
     204            'kl2zBLkmrTcEzMkoNoRLVidLi/9g+Z3I+1xRHX5EcAihxnbPRv'.
     205            'OTU9kZSmpKPy9FTGrLimPZ1H+UiyGaF67w6n7E1DwMngFDxGvc'.
     206            'w70v0xZUby5IxjlIyMssUJrJwVWkXBdbXvSvwEibcSdKCAFI16'.
     207            '4/sc0SRo9cGAGq1DwvQFzV6DVuBiV4zYnlEts6A2TSPcSiXoxo'.
     208            'QqJCEEFMbQ2b69o5qMiOOPqIMQkagu/aSL7waE8101WFShLjk9'.
     209            'yxgEvjRUiyYd+gwAjY2J9VpXfZ/JEXLhDp3OR6U4T97+hEnPwx'.
     210            'tv4HsRjy2tTQSFzQgDUnwSLBQRI+x1ZgcH87Vcv4SF19Kt0ezS'.
     211            '1h9s0Ma25pgr/YJfnLnEysok0+ezjM6EBLldGqKIJYuDRhOQEJ'.
     212            'Oih8X9Q0xmcXNjlCofBJgn78wxVz7L2YWf8tPPz1hnfjbjzfxN'.
     213            'qVwutq2etZXUQSXikcXGIgUiUkJSDIQMJgYGJsaB3c7b1qQ4GZ'.
     214            'xSkdGZIwMeNLfK6uezMnvJK3pLxeVixfvMsyVjSNSO6IV9adPG'.
     215            'AArkEEz8oUkFmBjYGO80qfd6pCWIayD59wIKcsjcKqufn7JO/S'.
     216            'xfyi+5c24pey5rZ09mJRNkiDdT/tzbkBr3SYkpMYpgEaIJSYhI'.
     217            'kSOY1GhilAQk5ntDIojxCZ/kf87Pl85xbuWEnLiUy+cW3NNuJX'.
     218            'MmY5meKf6mT7wZS+THdOjxlG06tIlIOMZxchSxcFFEGAwAGGME'.
     219            'jwyZYSnWL3cXWiIUbUI6hO/vxXuFOV84ycmlBWthNeflTjuzTi'.
     220            'lzJmM5s46Ej0J63/ZoPmoy6PYxtYVNhmfs0mbAND1mmKVMBY1L'.
     221            'mxA1LN7WgXQbCApNhKJHRIM+DQbv7yQGhjnJ5NgFuXBuxpu5mD'.
     222            'udm3LPuY7pmZLUE6L1SIJaIPFuDAqyw9lnwDYv6NFHkWJh4ZDB'.
     223            'wCBFD3uMxsTAwcBAiElpE/KcPg36dIiOvpsRxDCyhmlP2YY9ZU'.
     224            'v8NMb/1id+FGO0DTztkSXLOONUqeITsMkW2zwnJEIDFhYGx+A1'.
     225            'kwK4mASkvKDPc3p0iYhRRwYUhZLUTyV6Eu0t4s1Y4kcx6W6KaM'.
     226            'EZThcXH59RRhGEgIAddnBwNEBKqqpUtWBIF22YDIhJsbEkJqFN'.
     227            'qLtERHs7GnUkwISEQAf0uj30bY39PzbiC6qrDu2cExJ69Nhhhz'.
     228            '59UlIUipCQOnVi4sjG7ubJBy6um0C+he/0iDHQKIQERYyKFLqr'.
     229            'SI/W6kJCnvOcrWSLSquC1/Jw9Ks3R0FQKHr0uMc9bnCDGjX69A'.
     230            'H0XlcJkibN5jOe/alCZStHbjJL9lSMLkXExvCXRiDV6GZEeGeX'.
     231            '3TvvBVQoEjfBL/v0rT75Th7VU5C8gktI6NLlMY+5yU3WWGODDf'.
     232            'r098tHpNFNH7/2lKdXXdz7efLzVaqJIBOCmK8AJUlI6g0aV+9y'.
     233            '9+p7AR3bMQpTBWPy7yeN6fy0jNwewfpvC9Xe+3kFoUuXe9zj5n'.
     234            'BusEGHjh6GIAGawC2FWuvSvbbF1maFylZAsC1ISZADBiVNSJrP'.
     235            'eX73MY//skHP85z5+fnSxQsXj//4n39cmnPn7LbZlsajBmEnBL'.
     236            '1nuEGDG9x4aa5Ldz+h0RCuBqwBv1Wo+7vs9r7n++0MmYeAM+zB'.
     237            '+61EK1QUEnbbtN+9Bh3Hsebn54u//PdfLq9eWl2ZnZ1dSnaSwu'.
     238            'Pin40b9g3doKE0WoNIl65xj3v75njd3BBubQi6ExKmDWkMRKSl'.
     239            'tSbVKQcMao1Go5Ugb0+x53nOyZMnSysrKydXLq1cWlxa/McgCB'.
     240            'Yev3hU+GPrD3I5/q94k3pXYQY58q6B5Bs0HB//neaGx00gyWaz'.
     241            'VCoV7bquCoKAnZ0dfN/f03egLGj0m3XQNE1jdnY2/+WXXy6trq'.
     242            '6uzP3oR5eCIFi4detW5feXL1vr679Let37zVB3/mQytjXJwmSB'.
     243            'wikHp9ShY0RESqObwPrr5oBERKhUKly4cIFqtUq9XufmzZtsbW'.
     244            '2hXvuDwTTNtxZq8TyvsLy8vLS4uLgahOHphw8elL69fNlc++qr'.
     245            'uFOrNXPddm1cczVL5f5P+Lv5MuOJgTGxwYbZpZsCdeAq8M1Bcw'.
     246            'CGYeC6LtVqlRMnTjAyMkKn0yGXyx0N0LZt03Ec1zCMSrfXO37v'.
     247            'zp3S769csb+/ciXt1mrNdHf3ltZ6Lca8ZpJsduhtCdb2gEFJoQ'.
     248            'xADYHuHDS3f32lFEEQUK/XGRkZoVAocP78eZaXl9FaI/Jq25Uk'.
     249            'yWHAYrHozM/PlxYWFibTND32sFbLXrtyxVz76qukXas1M61WTW'.
     250            'm99gx+20TdN9jqtfjP7QzOwwYNp037Zd0DukDnIByA1pqdnR2+'.
     251            '++472u02Z8+eZWJiAsMwDsEBRNGBzYJpmsaJEyfyX3zxxdLS0t'.
     252            'KlVqu1dP3q1cLta9ekU6u1dat1J9b6Sk9kraV1rYXegW7apDYw'.
     253            'kFY6fPc4MNTw88bwfZ/NzU2UUnieRxAEiAiGcXiXfcigiIjruo'.
     254            'VyubxkWdbK7fX1xWvffFMInjzBM82uMT5+p++6V1UUrSe7u03t'.
     255            '+8lezlKt3gHyl0aSJDQaDa5fv876+vo+w6FzDq1BpZRsb2/bly'.
     256            '9f9vL5/Njdu3fzG0+eMJHNxsfn532vXN5NPG/7abPZal6/Hvfe'.
     257            'kroPHfsm98f7AHW9Xo+//vrrlmVZm71+37QNw3JnZ9PK4uJGpV'.
     258            'pt4Dh+vLGhsrmcfv1iHzu01m89HjIdCon2fb8TBMHtvYeRUn50'.
     259            '1Oj4vqp3Ok1f5LYSadfr9dQfDN642P/XeF2DA+SBAuA4jkOhUK'.
     260            'BQKESO43S11p3BYBDt7u4y+CtB/i/q7jp1GMiw2AAAAABJRU5E'.
     261            'rkJggg==' ;
     262
     263//==========================================================
     264// File: ppl_blue.png
     265//==========================================================
     266        $this->imgdata_large[3][0]= 2284 ;
     267        $this->imgdata_large[3][1]=
     268            'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
     269            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
     270            'B3RJTUUH0wMLFRAiTZAL3gAACHlJREFUeJy9mGtv29YZgJ9zKF'.
     271            'F3y/Q9jh05tuQkarKgbYasde0UBdZgwNou/Vqga/sD9mP2B4a1'.
     272            'BbZ9atFPxb5sqOtmXbI19bqsluPYiR3HN90vFEWRZx/IJI5zqa'.
     273            'x0OwBBSgR5Hj7v+55zSEFXTUgIJyA9C6/9RsjMjAyFIxxJCDc7'.
     274            'iBqKgyZACGg3G2x9+xXf/fG33P3mC9qNKsp1O+1JdkEnQTdgIO'.
     275            'ttCSMUi8gj072MnugllAyB9G8rBGi6RsToJTF6iuRoFi1kHKZf'.
     276            '7fB8Iggj0/Dy23D2dakNTR3JDsXPvzstxmZGRMER1EwHhQAEgE'.
     277            'CLhIkPD6InY9S3djGLJVBtQP1Qb4HDAyoJYQOOZkPx49nhTH9i'.
     278            '7MUBGT7egxkJgd70wZS/CUkoZtA/fRoE1DZ2ACiv52ibReCp4e'.
     279            '7CIEHomxDiuVdGTqUnf/ZeOjR8fpiVXZul5ZrY3bWwbdcLr/dA'.
     280            'AAIpAwQjUWIjQ+g9HZvswiCgBVF9/SI6OSLGzo0i+oLi6+Utbq'.
     281            '+bKEftgwOE/0Ohocf66M+cBjo22U2RQLIHMhmYnvaOpR9S8bSU'.
     282            'UqCURGpRkuMZMm9cIvPGJZLj0yBjT2LprkiSkykx9cuXIhOnUs'.
     283            'm+QNC2XdG02ggBTcvFabsPWwTPpBAChSCgh4kYBpoeplWp47Qs'.
     284            '7EYDt21xINzd5GCAxLExRl89Z+nHjpbKMmjbmkgfDzI0JEW53K'.
     285            'Jaa6NcAOEX8v52uJzsBlAS6u0hcnTIccPRqhWPCUcLD+s1EaUp'.
     286            'HCEhEMCyHNpt9SjgIU12A6iw6xb123vYhaaKjB9tlgMD5X+uBp'.
     287            'zdkpg6azA8EaNQtKlVba+Xez4eCntnJrsDdFsW5nYFpxlFN846'.
     288            'DXe8utkM4mhi+EgQmjYbS2WqexZKk6BpjwJ2YlK5VjeA3pNDiH'.
     289            'YjRWPzPE7tmBo8EWwGhkXx+z3uXL7D3rU97LIF8RBEAl6lK/Uo'.
     290            '6JNM1rZ2aTcr3eUgIQOGTgbdwXMGyRejenLYTvQGbAdRuetSud'.
     291            'OivVuFZgtCEgICghICnZoMhmlVTPR49LCAEkQUhk/B7KXe0MWf'.
     292            'nxj8xVR/cDheK14WZmtVMJSBnlGoN6FmQq0FLfdwJgORKPHRo/'.
     293            'Snzx4G0F/FjJ4KiOdmjPCrrx8bffnMybMv9MQGNG3rzlVqtR1B'.
     294            'sh/CYXCD4Aag1oCW7ZnUOjSp6WFi/QNEB8Y7BfTNjZyCmUvJ0I'.
     295            'XXT47MTp98Ybon9VZCk8cVazfqlNargsY34G7ByAlIjkHd9CCr'.
     296            'LbBdiHViUgiECuDKYCdz8b2cywREdiYZOj8zNnLuzOTzx6ODp+'.
     297            'OaGaqwVzBFqz0Idhz2loE7YEwBLaAJLQcKbW8qjAcBF5Jh0AMP'.
     298            'IOHe6kxgtb3UMO2OxkF//ffK28nQqxfvm3szrtnDVa799Qb/+v'.
     299            'NtsbNSpm3tAv8B+w7Ub0FhAyoBcMPec9oK6raXk48ziQBXQcmC'.
     300            'pT3YqHa0mpEBkTR6wz/Jjo2cy04+fzwxdDquNfQKO7sFUbpu0c'.
     301            'wp3JoAYsA42Bbkl4GCryUNDEM7Avm6Z/CgSYBWG8pNuFuDu1Wo'.
     302            'tjoxKIJGeHIiM/jmK9NnX5ycuJQMtUcqXPvLDTa+qIie4hAJ1U'.
     303            'vdrmO2HaDfB931twJgAn1A4lGT96obPHPLBbhVgUoTHHWo9aAA'.
     304            'JVAKpyKEmQNzWRENAsL18ycKjAFN/9gCNvzLB/390MMmE7pnDi'.
     305            'Bvwt0K5Jv3O+0oB22nJ1Vvjb/UMhOpcKknqN1OiMB2DNHU2G5s'.
     306            'sVndpGJVcZXjX1IAlvw9PmhRQcOFPhsSDkiBrQR1G7brgs0a7D'.
     307            'ag3FK4rguqBXarI4Nt1SJv5gls7TEWtJDRBO2GwnIs8maevFnA'.
     308            'Gx6awLZvzeTBu4kFbLigijC47pscpx0xyDfkvtUEnlarCDtrUC'.
     309            't2HGIhvPHVdVwqjTIrxRU2a5uUrYoP0QZ2gMvACl7+3V/LuKDq'.
     310            'sJuDy597516+CEezIHXv7vcgXQu2l+Bvn8He9Y4AE4kgk5P9DE'.
     311            'R6aFdq5Et5Nit3yTf3m9sBcsAN3+D98c0Fit5JawE25r1zg1Fo'.
     312            '5B8GFD7g+nVYnu8EUEop9XTa0N/9dUbqcphP/rDJzbUClVbpgR'.
     313            'y2fXM3fND95qj75J8AC6BWPINfVSBieK+x+6cS5UCzCLu3oFV9'.
     314            'GqCMx2NGOp2Znpv7aXZudsool3T5J/179sxVlHJ4kGPrP2COBX'.
     315            '/7DmiApWCjxIMXpYNznYuXM+6TAKWUMppOZzLvv//ery5cuDCT'.
     316            'SqVS336bCwr1JfAPB9r+2KAFwJS+OcETzZHz/7v3etl6ipz77X'.
     317            'GAMh6PG+l0OjM3NzczOzs3k0pNnFlbW43+e/GKtMqrblSsF03V'.
     318            'WHcJA0PjIAzvg9JTze2H67g9DjAwOTmZ+uCDD96anZ2dnZiYmF'.
     319            '5dW41++Lvfa1fnr7qllVK9103mXNTnJgPA+YugsvB3HTaEl+Qs'.
     320            'AZ/yeHPPDCiTyaRx5syZbGoilV1dW00szC9oV+avusuLy0Xd0X'.
     321            'MgFkDM+zkYBZEHV8f7wwKu84zmngQoNU0LaZoWUa4K31y5qX/8'.
     322            '4cfyyvwVN5/L10NOKNeg8UmDxoKF5Vfj1xXAgD0JrgAcvBDfel'.
     323            'a4g4AykUgY6XR6emJiIru2ttZXq9S0K19eUcuLy8WQE8o5OAsN'.
     324            'Ggsmpl+NpoL1g9X4UBU+C9xDgEKIwNTUVOqdd955M9mbnJ3/cj'.
     325            '6Vu5aTheXCQXNdVeMzAwJSCGEA2XKpnF1cXIzlFnOVhJPIKdR+'.
     326            'c88ctq4AlVKsrKzw0UcfKcC5uXqzXnNqSzb2pwLxOHP/l7Z/BN'.
     327            'eB01LKt4HTrusKvGr8jB+hGn8MQAkYQMrfw4Nq/MFPtf+rdvDb'.
     328            'k8QL+/5Z4Uepxm7bfwHuTAVUWpWaqAAAAABJRU5ErkJggg==' ;
     329
     330//==========================================================
     331// File: ppl_green.png
     332//==========================================================
     333        $this->imgdata_large[4][0]= 2854 ;
     334        $this->imgdata_large[4][1]=
     335            'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABm'.
     336            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
     337            'B3RJTUUH0wMLFQ4hANhluwAACrNJREFUeJytmF1zE1eagJ+3u9'.
     338            'XdkvUty2AbmLEtEzDBgZ0UpDBOalNTUzU3czl7tct/2n+wt3M/'.
     339            'NVM12SSTQQSyW2TA+QAJQogtYYFtyfrqL3WfvWj5g8AEjzfvhS'.
     340            'SXjk8//Zz3Pf3qCMcJAWxMKlT4kH+jwu/FknnJSUItKFHzCrKA'.
     341            'BggBQx5ziz/wn/yBz3hED4/oaJfSjgVoYjJJgTLTZCjohp7IGT'.
     342            'k5aZ4kb+bRTR30Q7djj8f/kpPMUSCFedRL6W8e8qMQNE6S4xpv'.
     343            'c5HrTPFubiJ3ZnlyOXV59rJYU5Z00h1c3d0brxAiUkScRijisk'.
     344            '6XLTyiN3s8HuAJpniXa/q8/pt8Or+0kF8oXJm5YiydWcIpOrJu'.
     345            'rjOQwd54AQwsMpTJYhPSoYuLQ58An/DnBQSdImXO8avsTPbqpc'.
     346            'lLp67OXDVzMznZLGxSs2qyIRu4at8gKHQEC50kE1icxqCAdxST'.
     347            'xjEA44tqaJlERl8uLWvvnX5PHuQfcCdxh5qq0aX76vj4WgWyXO'.
     348            'QiNgBP8IAaddr08X8+wHFmJSQhBbPAZGoSZSt5wQs6qoNC7UEd'.
     349            '4AEoLIQSCaCCy78Dv8Tiv1hjjW1CRj8XIAgEKqDtt9keboMJZa'.
     350            'vMjuzQVd3Xr9prTJo+GF/jKZea95R25Lxs8jg5qFGiwDnOS0mW'.
     351            'NE0rjNRIt3WbklUCA9mV3Zdz8OBT/JfCQLB0SKYVVjGFYSfx/E'.
     352            '26ow4e6uDujlPFQpE0FU6P8qNTHdXJdEdda0qf0itWBVM3pa/3'.
     353            'ccUlIECJet0cAJoeYk5EZCeS5IwEoerSxccJBwRqFFf38QCTaO'.
     354            'TRVFKJm3NTbtLNSyh2IkhIXsvLCesEGNCWdmwyruSD/z9kUlRc'.
     355            '3bqNlSxhJNJ43p5JITrOEis8Qtr0cXEpU/JT/pmO18n2vb42pU'.
     356            '3JnDnHMBqyPlpnoAaxhr2llv1ZUBqEGlqYwDQMsskMOcMgVL3Y'.
     357            'ZOQTHAcQQiIGjHCwCaiovjrv4hbcpKuJJjIcDHm685RGr4GLCx'.
     358            'YHkAcrLoAoDSLBiAQrMkjqybHJCbxgh+7xAC1MpsgzwRwD3qHL'.
     359            'WyTIBdlAa6u2rHfXaew06PV78ZZjAwleNnkolECoH5i090wOcY'.
     360            '+TgwYzFHiPi1zkOkXexeAMASnVU+LiyiA1wFUuaqggACLizeWw'.
     361            'ycMzyssmVYKkbpGyC5T+OUALk2mKLHKWf+ED/az+YW42d66YL+'.
     362            'aNrmEEzQCFEnKw368EgEvcN1m80eTIQIt0TFOjMJHkzNEBBYPp'.
     363            'sblf8QHzrORO5JaWZ5ZLl6cuJyyxpNPv4PZdoT+GyIxBfI5uUg'.
     364            'eJMCwP2/bIHO1JEudcgUUWOceKNq99mCvnzs5PzRcuTV4y5mRO'.
     365            'SMIjo47z5S7a94oQCNKgJsZwO7D/IDNg3/LLhRNXt4JohBb4aG'.
     366            '82GLdXcf93mQ+Y43r2RHZp+cRy6cqJK4l8MS+tdItaqiYtc0Mm'.
     367            'QpfJARh98HYh9IiXVcaAo58wGb+LBAjbSPgCOcoSa0wzxXtc08'.
     368            '/pv8mfyL+9MLVQvDJ1JVHJV6SZbFI1qtTsB+KlehRtRTGE8Afo'.
     369            'P4DRcAxiEudhAHjjzz+ubgX4oHowakHQOlqzICQwyVPITGVOXi'.
     370            'xfLF6aumzmczl5lHzMff2+fCdPaGttEkXoLQAO9B7C6EugPYby'.
     371            'gVPjGXc5eIbNAJPjGwiAbaAJUQv8wVG7GROkJFpyOqn/ovgLba'.
     372            '44L0+sDaraXb6jzq7aBQWjBOyUoHcaopOgmaA3IRyNDZnA1HjO'.
     373            'HSBkr7eEFDAEngHrQCf+/s2A8cSiSkqcKUeeTjwFy2Jd78t3+L'.
     374            'TR4itIiBLwLQhzkJyB5Cx4HXDaENVQCBAQcRqFIHTRaBIvuYXg'.
     375            'AdsouuNxEL0ZUBHnSQp66R73zYfUtQ6OytKT8RckQAJQoLtgO5'.
     376            'BJgj0D/WfgdyHaAHx8THoUcbGx8ciwhUl3bDEiToURPooeI7pH'.
     377            'MziK9Yd9nU5a6GgKjOH41vsgI4hAcyC5AZkapF+AoYNrjjsuhx'.
     378            'FbtPmeB5ykyQQzTPAWAQWC8S9oAI0QRRuPb9jkmyMZNAOTklvC'.
     379            'GGYZaFkGmkVAh8h4DtKFMIBunG+pB5B5AIkGBDsQ+qBiL20caj'.
     380            'zhJknq5KlgMkLjJHJos4kYEbFJi5vc5eYbATVN02bNWe19+32t'.
     381            'aJWlFm3wbf8Rz5NbDFJdlOFBF/g7cBf0JkrbBb+F6j1DOduEkU'.
     382            '8bWCOiSofPWadBnSZDWmgUkEMGhZCINut8S/0NBtPptFlZrBSu'.
     383            'vnt1+ndnflfIp9OJ/279Ubbbd+lP7KBKPoEBsgnqLph/BRzwdS'.
     384            'LnBUFvHcfdpRsGPAGqwMco6jynz+e0SPKYCHMfLX5VKHwcenR+'.
     385            'Igd1XTcqlUr+xn/cePv91fevzy8sLO2OtrOpWkqL7gXKSAVRdh'.
     386            'ZFEmEXoYkwBNqovoc/3GHH3aUR+jwC1oD/AWrANi4hGwyBzqEG'.
     387            'Vvb77Dgi0eT1VZzJZMxKpVJYXV1dXF1dXVm6sPSvruue3Xzcyj'.
     388            '6/syvDzwj0lNazK6Fj5LFCRZouZpBABj6jXouu3+Np6HNvDHaf'.
     389            'g91t74msbMuOJicnSSaTKKUQEUQEpRSO69But1/dB0VEm5uby9'.
     390            'y4cWNpdXX1+sLCworrume//PuXpeqnVeOban0U1PW2kcx+O9L7'.
     391            'Te9sUB4lWFR9SqNtNGcHx+/RDD2+Am4D94CnQA8OjjlEhMnyJC'.
     392            'srK8zOzu7BiYioMAzZ2Njg9u3brwIqpSSXy2WXl5eXLly4sOo4'.
     393            'zoV6vV6oflrVP/7Tx8Hmw1Zb6ydqmpWp7ha8h4O3gjOhzVANmF'.
     394            'XPMNQWvdDnCXCXuHR+APqH4fbCtm2mp6eZn59H13WJuYXRaKSU'.
     395            'UiSTyVcBdV3XDcOwRaTU7/en19bWCn/79G+JL/76RbhZ22y7u+'.
     396            '6ahl71nPDz/nO17m7wAxlabFOihy4+DvAcqAMbPzZ3OFzX5dmz'.
     397            'Z2iahoiosUUVhiGNRgPHcV4GzGQy5uLiYuH8+fMzo9FoslarJW'.
     398            '9+elP75E+fBJu1zY7qqpqBUW3T/niohnVvy+1zm5aVtp+WE2XT'.
     399            'nrHFzbjh1tYLz3XdPjD4R3BKKba2tqhWq4dzUO3noBPn4H5PKy'.
     400            'LaO++8U7hx48byhQsXVne7u6tf3/v64t3P7mbq9+odt+OuaWi3'.
     401            'PLxbW2ytubjbQCgiMnt6VlaurWgz0zM0m02q1WrUaDSUUuqI56'.
     402            'ivDxE5MCgiYllWtlwuL5mmufLV/a/O/uXPf9Ff1F+80Lv6Yx29'.
     403            '2qHzyZBh3cdvc7gaTZuZkzPh/Py8ACqVSv1/uPZDKXUAGEWRtF'.
     404            'qtxEcffZTL5XLF+2v39fqjeivshA/TpP83JLwzYFBzcA4370Cc'.
     405            'S81nTRBUs9lkOByi1GuOPI4Rh3+26JZlnSkWi781DOPXvV4v3+'.
     406            '/2G0R8kSBxB/jew+tERK+c49m2TblcxrZtXNfl+fPneJ6HZVmU'.
     407            'y2VJJpNyaJ9TSinlOA5bW1u4rntkQA0oAG8D54gb9W3ianxM3A'.
     408            'e/cn73U3Hq1Cm5du2aPjs7a+ztcSIShmE4ajQa6tatWzQajZ+0'.
     409            'fbiKI+It4SvijVUj7kL2qvGfgkskEqTTaZmcnDROnTplJhIJTU'.
     410            'QiwPd9P/Q8T6XTaQzDIAiCfzjP/wFVfszuFqdHXgAAAABJRU5E'.
     411            'rkJggg==' ;
     412
     413
     414//==========================================================
     415// File: pp_red.png
     416//==========================================================
     417        $this->imgdata_small[0][0]= 384 ;
     418        $this->imgdata_small[0][1]=
     419            'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
     420            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
     421            'B3RJTUUH0wMJFhouFobZrQAAAQ1JREFUeJyV1dFtwyAQBuD/og'.
     422            'xQdYxa8gRY6hJ0jK6QdohMkTEuE5wUj5ERen05IoLvID7Jkn2G'.
     423            'j8MgTMyMXqRlUQBYq9ydmaL2h1cwqD7l30t+L1iwlbYFRegY7I'.
     424            'SHjkEifGg4ww3aBa/l4+9AhxWWr/dLhEunXUGHq6yGniw3QkOw'.
     425            '3jJ7UBd82n/VVAlAtvsfp98lAj2sAJOhU4AeQ7DC1ubVBODWDJ'.
     426            'TtCsEWa6u5M1NeFs1NzgdtuhHGtj+9Q2IDppQUAL6Cyrlz0gDN'.
     427            'ohSMiJCt861672EiAhEhESG3woJ9V9OKTkwRKbdqz4cHmFLSFg'.
     428            's69+LvAZKdeZ/n89uLnd2g0S+gjd5g8zzjH5Y/eLLi+NPEAAAA'.
     429            'AElFTkSuQmCC' ;
     430
     431//==========================================================
     432// File: pp_orange.png
     433//==========================================================
     434        $this->imgdata_small[1][0]= 403 ;
     435        $this->imgdata_small[1][1]=
     436            'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
     437            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
     438            'B3RJTUUH0wMJFhwAnApz5AAAASBJREFUeJyN1dFthDAMBuDf7S'.
     439            '3BCm2VCRKpS4QxbhikW6IewzcBqm6Fm6JyH7iEEByCn5AJH38g'.
     440            'BBIRHNUzBAWAGNfe/SrUGv92CtNt309BrfFdMGPjvt9CD8Fyml'.
     441            'ZZaDchRgA/59FDMD18pvNoNyHxMnUmgLmPHoJ+CqqfMaNAH22C'.
     442            'fgqKRwR+GRpxGjXBEiuXDBWQhTK3plxijyWWvtKVS5KNG1xM8I'.
     443            'OBr7geV1WupDqpmTAPKjCqLhxk/z0PImQmjKrAuI6vMXlhFroD'.
     444            'vfdqITXWqg2YMSJEAFcReoag6UXU2DzPG8w5t09YYsAyLWvHrL'.
     445            'HUy6D3XmvMAAhAay8kAJpBosX4vt0G4+4Jam6s6Rz1fgFG0ncA'.
     446            'f3XfOQcA+Acv5IUSdQw9hgAAAABJRU5ErkJggg==' ;
     447
     448//==========================================================
     449// File: pp_pink.png
     450//==========================================================
     451        $this->imgdata_small[2][0]= 419 ;
     452        $this->imgdata_small[2][1]=
     453            'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
     454            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
     455            'B3RJTUUH0wMJFhsQzvz1RwAAATBJREFUeJyd1MFthDAQheF/oi'.
     456            'gF+JYWQKICkCJRA1vGtrDbxFbhGvY0HVjCLeS2BeTiHFgTB2wg'.
     457            'eRISstCnmcG2qCpbuXf3ADBQzWsPfZfS9y9HsEu4/Fo33Wf4Fx'.
     458            'gxL3a1XkI3wbTNXHLoboVeLFUYDqObYBy+Fw/Uh9DdCmtOwIjF'.
     459            'YvG76CZoOhNGRmpO8zz30CJoOhMAqlDxFzQLppgXj2XaNlP7FF'.
     460            'GLL7ccMYCBgZERgCvXLBrfi2DEclmiKZwFY4tp6sW26bVfnede'.
     461            'e5Hc5dC2bUgrXGKqWrwcXnNYDjmCrcCIiQgDcFYV05kQ8SXmnB'.
     462            'NgPiVN06wrTDGAhz5EWY/FOccTk+cTnHM/YNu2YYllgFxCWuUM'.
     463            'ikzGx+2Gc+4N+CoJW8n+5a2UKm2aBoBvGA6L7wfl8aoAAAAASU'.
     464            'VORK5CYII=' ;
     465
     466
     467//==========================================================
     468// File: pp_blue.png
     469//==========================================================
     470        $this->imgdata_small[3][0]= 883 ;
     471        $this->imgdata_small[3][1]=
     472            'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAACi1'.
     473            'BMVEX///8AAAAAADMAAGYAAJkAAMwAAP8zAAAzADMzAGYzAJkz'.
     474            'AMwzAP9mAABmADNmAGZmAJlmAMxmAP+ZAACZADOZAGaZAJmZAM'.
     475            'yZAP/MAADMADPMAGbMAJnMAMzMAP//AAD/ADP/AGb/AJn/AMz/'.
     476            'AP8AMwAAMzMAM2YAM5kAM8wAM/8zMwAzMzMzM2YzM5kzM8wzM/'.
     477            '9mMwBmMzNmM2ZmM5lmM8xmM/+ZMwCZMzOZM2aZM5mZM8yZM//M'.
     478            'MwDMMzPMM2bMM5nMM8zMM///MwD/MzP/M2b/M5n/M8z/M/8AZg'.
     479            'AAZjMAZmYAZpkAZswAZv8zZgAzZjMzZmYzZpkzZswzZv9mZgBm'.
     480            'ZjNmZmZmZplmZsxmZv+ZZgCZZjOZZmaZZpmZZsyZZv/MZgDMZj'.
     481            'PMZmbMZpnMZszMZv//ZgD/ZjP/Zmb/Zpn/Zsz/Zv8AmQAAmTMA'.
     482            'mWYAmZkAmcwAmf8zmQAzmTMzmWYzmZkzmcwzmf9mmQBmmTNmmW'.
     483            'ZmmZlmmcxmmf+ZmQCZmTOZmWaZmZmZmcyZmf/MmQDMmTPMmWbM'.
     484            'mZnMmczMmf//mQD/mTP/mWb/mZn/mcz/mf8AzAAAzDMAzGYAzJ'.
     485            'kAzMwAzP8zzAAzzDMzzGYzzJkzzMwzzP9mzABmzDNmzGZmzJlm'.
     486            'zMxmzP+ZzACZzDOZzGaZzJmZzMyZzP/MzADMzDPMzGbMzJnMzM'.
     487            'zMzP//zAD/zDP/zGb/zJn/zMz/zP8A/wAA/zMA/2YA/5kA/8wA'.
     488            '//8z/wAz/zMz/2Yz/5kz/8wz//9m/wBm/zNm/2Zm/5lm/8xm//'.
     489            '+Z/wCZ/zOZ/2aZ/5mZ/8yZ///M/wDM/zPM/2bM/5nM/8zM////'.
     490            '/wD//zP//2b//5n//8z///9jJVUgAAAAAXRSTlMAQObYZgAAAA'.
     491            'FiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElN'.
     492            'RQfTAwkWGTNerea3AAAAYUlEQVR4nHXNwQ3AIAxDUUfyoROxRZ'.
     493            'icARin0EBTIP3Hp1gBRqSqYo0seqjZpnngojlWBir5+b8o06lM'.
     494            'ha5uFKEpDZulV8l52axhVzqaCdxQp32qVSSwC1wN3fYiw7b76w'.
     495            'bN4SMue4/KbwAAAABJRU5ErkJggg==' ;
     496
     497//==========================================================
     498// File: pp_green.png
     499//==========================================================
     500        $this->imgdata_small[4][0]= 447 ;
     501        $this->imgdata_small[4][1]=
     502            'iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABm'.
     503            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
     504            'B3RJTUUH0wMJFhkLdq9eKQAAAUxJREFUeJyN1LFVwzAQxvH/8f'.
     505            'IeDS0FLKABlN6eIwPYAzCHB0gWYI2jj+i1ABUTQN4TRSQ7iiWZ'.
     506            'qxLn9Mt9ydmiqrSq930AYFiu6YdKrf/hP1gYQn6960PxwBaYMG'.
     507            'E9UA3dBFtVQjdBOQmBakLennK0CapRwbZRZ3N0O/IeEsqp3HKL'.
     508            'Smtt5pUZgTPg4gdDud+6xoS97wM2rsxxmRSoTgoVcMZsXJkBho'.
     509            'SmKqCuOuEtls6nmGMFPTUmxBKx/MeyNfQGLoOOiC2ddsxb1Kzv'.
     510            'ZzUqu5IXbGDvBJf+hDisi77qFSuhq7Xpuu66TyJLRGbsXVUPxV'.
     511            'SxsgkzDMt0mKT3/RcjL8C5hHnvJToXY0xYRZ4xnVKsV/S+a8YA'.
     512            'AvCb3s9g13UhYj+TTo93B3fApRV1FVlEAD6H42DjN9/WvzDYuJ'.
     513            'dL5b1/ji+/IX8EGWP4AwRii8PdFHTqAAAAAElFTkSuQmCC' ;
    514514    }
    515515}
  • trunk/client/modules/Elezioni/grafici/imgdata_squares.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        IMGDATA_SQUARES.INC
    4 // Description: Base64 encoded images for squares
    5 // Created:     2003-03-20
    6 // Ver:         $Id: imgdata_squares.inc.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        IMGDATA_SQUARES.INC
     4// Description: Base64 encoded images for squares
     5// Created:     2003-03-20
     6// Ver:         $Id: imgdata_squares.inc.php 860 2007-03-23 19:16:19Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    1212    protected $name = 'Squares';
    1313    protected $an = array(MARK_IMG_SQUARE =>'imgdata');
    14 
    15     protected $colors = array('bluegreen','blue','green',
    16    'lightblue','orange','purple','red','yellow');
    17     protected $index  = array('bluegreen' =>2,'blue'=>5,'green'=>6,
    18    'lightblue'=>0,'orange'=>7,'purple'=>4,'red'=>3,'yellow'=>1);
     14   
     15    protected $colors = array('bluegreen','blue','green', 
     16                        'lightblue','orange','purple','red','yellow');
     17    protected $index  = array('bluegreen' =>2,'blue'=>5,'green'=>6, 
     18                        'lightblue'=>0,'orange'=>7,'purple'=>4,'red'=>3,'yellow'=>1);
    1919    protected $maxidx = 7 ;
    2020    protected $imgdata ;
    2121
    2222    function ImgData_Squares () {
    23         //==========================================================
    24         //sq_lblue.png
    25         //==========================================================
    26         $this->imgdata[0][0]= 362 ;
    27         $this->imgdata[0][1]=
    28      'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAABm'.
    29      'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
    30      'B3RJTUUH0wMLFgojiPx/ygAAAPdJREFUeNpj/P377+kzHx89/c'.
    31      'VAHNBQ5VBX52HavPWWjg6nnDQbkXoUFTnnL7zD9PPXrz17HxCj'.
    32      'E6Jn6fL7H7/+ZWJgYCBGJ7IeBgYGJogofp1oehDa8OjE1IOiDa'.
    33      'tOrHoYGBhY0NwD0enirMDAwMDFxYRVD7ptyDrNTAU0NXix6sGu'.
    34      'jYGBgZOT9e/f/0xMjFyczFgVsGAKCfBza2kKzpl3hIuT1c9Xb/'.
    35      'PW58/foKchJqx6tmy98vbjj8cvPm/afMnXW1JShA2fNmQ9EBFc'.
    36      'Opnw6MGjkwm/Hlw6mQjqwaqTiRg9mDoZv//4M2/+UYJ64EBWgj'.
    37      'cm2hwA8l24oNDl+DMAAAAASUVORK5CYII=' ;
     23//==========================================================
     24//sq_lblue.png
     25//==========================================================
     26        $this->imgdata[0][0]= 362 ;
     27        $this->imgdata[0][1]=
     28            'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAIAAADZrBkAAAAABm'.
     29            'JLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsRAAALEQF/ZF+RAAAA'.
     30            'B3RJTUUH0wMLFgojiPx/ygAAAPdJREFUeNpj/P377+kzHx89/c'.
     31            'VAHNBQ5VBX52HavPWWjg6nnDQbkXoUFTnnL7zD9PPXrz17HxCj'.
     32            'E6Jn6fL7H7/+ZWJgYCBGJ7IeBgYGJogofp1oehDa8OjE1IOiDa'.
     33            'tOrHoYGBhY0NwD0enirMDAwMDFxYRVD7ptyDrNTAU0NXix6sGu'.
     34            'jYGBgZOT9e/f/0xMjFyczFgVsGAKCfBza2kKzpl3hIuT1c9Xb/'.
     35            'PW58/foKchJqx6tmy98vbjj8cvPm/afMnXW1JShA2fNmQ9EBFc'.
     36            'Opnw6MGjkwm/Hlw6mQjqwaqTiRg9mDoZv//4M2/+UYJ64EBWgj'.
     37            'cm2hwA8l24oNDl+DMAAAAASUVORK5CYII=' ;
    3838
    39         //==========================================================
    40         //sq_yellow.png
    41         //==========================================================
    42         $this->imgdata[1][0]= 338 ;
    43         $this->imgdata[1][1]=
    44      'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAWl'.
    45      'BMVEX////+/+H+/9/9/9v8/8P8/8H8/7v8/7n6/4P5/335/3n5'.
    46      '/3X4/1f4/1P3/031/w30/wn0/wPt+ADp9ADm8ADk7gDc5gDa5A'.
    47      'DL1ADFzgCwuACqsgClrABzeAC9M0MzAAAAAWJLR0QAiAUdSAAA'.
    48      'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEDlOgDj'.
    49      'EAAAB+SURBVHjaVcpbCsQgDEDRGERGKopjDa2a/W9zfLWj9/Nw'.
    50      'Ac21ZRBOtZlRN9ApzSYFaDUj79KIorRDbJNO9bN/GUSh2ZRJFJ'.
    51      'S18iorURBiyksO8buT0zkfYaUqzI91ckfhWhoGXTLzsDjI68Sz'.
    52      'pGMjrzPzauA/iXk1AtykmvgBC8UcWUdc9HkAAAAASUVORK5CYI'.
    53      'I=' ;
     39//==========================================================
     40//sq_yellow.png
     41//==========================================================
     42        $this->imgdata[1][0]= 338 ;
     43        $this->imgdata[1][1]=
     44            'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAWl'.
     45            'BMVEX////+/+H+/9/9/9v8/8P8/8H8/7v8/7n6/4P5/335/3n5'.
     46            '/3X4/1f4/1P3/031/w30/wn0/wPt+ADp9ADm8ADk7gDc5gDa5A'.
     47            'DL1ADFzgCwuACqsgClrABzeAC9M0MzAAAAAWJLR0QAiAUdSAAA'.
     48            'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEDlOgDj'.
     49            'EAAAB+SURBVHjaVcpbCsQgDEDRGERGKopjDa2a/W9zfLWj9/Nw'.
     50            'Ac21ZRBOtZlRN9ApzSYFaDUj79KIorRDbJNO9bN/GUSh2ZRJFJ'.
     51            'S18iorURBiyksO8buT0zkfYaUqzI91ckfhWhoGXTLzsDjI68Sz'.
     52            'pGMjrzPzauA/iXk1AtykmvgBC8UcWUdc9HkAAAAASUVORK5CYI'.
     53            'I=' ;
    5454
    55         //==========================================================
    56         //sq_blgr.png
    57         //==========================================================
    58         $this->imgdata[2][0]= 347 ;
    59         $this->imgdata[2][1]=
    60      'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAZl'.
    61      'BMVEX////0+vv0+vrz+fry+frv+Png7e/d7e/a6+zY6+250tSz'.
    62      '0tSyztCtztGM0NWIz9SDzdNfsLVcrrRZrbJOp61MpqtIr7dHn6'.
    63      'RErrZArLQ6q7M2g4kygYcsp68npa4ctr8QZ20JnqepKsl4AAAA'.
    64      'AWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU'.
    65      '1FB9MDCxYEByp8tpUAAAB7SURBVHjaVcjRFoIgDADQWZpWJpjY'.
    66      'MsnG//9kzIFn3McLzfArDA3MndFjrhvgfDHFBEB9pt0CVzwrY3'.
    67      'n2yicjhY4vTSp0nbXtN+hCV53SHDWe61dZY+/9463r2XuifHAM'.
    68      '0SoH+6xEcovUlCfefeFSIwfTTQ3fB+pi4lV/bTIgvmaA7a0AAA'.
    69      'AASUVORK5CYII=' ;
     55//==========================================================
     56//sq_blgr.png
     57//==========================================================
     58        $this->imgdata[2][0]= 347 ;
     59        $this->imgdata[2][1]=
     60            'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAZl'.
     61            'BMVEX////0+vv0+vrz+fry+frv+Png7e/d7e/a6+zY6+250tSz'.
     62            '0tSyztCtztGM0NWIz9SDzdNfsLVcrrRZrbJOp61MpqtIr7dHn6'.
     63            'RErrZArLQ6q7M2g4kygYcsp68npa4ctr8QZ20JnqepKsl4AAAA'.
     64            'AWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU'.
     65            '1FB9MDCxYEByp8tpUAAAB7SURBVHjaVcjRFoIgDADQWZpWJpjY'.
     66            'MsnG//9kzIFn3McLzfArDA3MndFjrhvgfDHFBEB9pt0CVzwrY3'.
     67            'n2yicjhY4vTSp0nbXtN+hCV53SHDWe61dZY+/9463r2XuifHAM'.
     68            '0SoH+6xEcovUlCfefeFSIwfTTQ3fB+pi4lV/bTIgvmaA7a0AAA'.
     69            'AASUVORK5CYII=' ;
    7070
    71         //==========================================================
    72         //sq_red.png
    73         //==========================================================
    74         $this->imgdata[3][0]= 324 ;
    75         $this->imgdata[3][1]=
    76      'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'.
    77      'BMVEX////++Pn99/j99ff99fb98/X98/T98PL55uj43+P24+bw'.
    78      'kKPvjaHviJ3teJHpxMnoL2Pjs73WW3rWNljVWXnUVnbUK1DTJk'.
    79      '3SUHPOBz/KQmmxPVmuOFasNFOeIkWVka/fAAAAAWJLR0QAiAUd'.
    80      'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEHd'.
    81      'ceT+8AAABtSURBVHjaVchbAkMwEAXQq6i3VrQiQfa/zDYTw8z5'.
    82      'PCjGt9JVWFt1XWPh1fWNdfDy+tq6WPfRUPENNKnSnXNWPB4uv2'.
    83      'b54nSZ8jHrMtOxvWZZZtpD4KP6xLkO9/AhzhaCOMhJh68cOjzV'.
    84      '/K/4Ac2cG+nBcaRuAAAAAElFTkSuQmCC' ;
     71//==========================================================
     72//sq_red.png
     73//==========================================================
     74        $this->imgdata[3][0]= 324 ;
     75        $this->imgdata[3][1]=
     76            'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'.
     77            'BMVEX////++Pn99/j99ff99fb98/X98/T98PL55uj43+P24+bw'.
     78            'kKPvjaHviJ3teJHpxMnoL2Pjs73WW3rWNljVWXnUVnbUK1DTJk'.
     79            '3SUHPOBz/KQmmxPVmuOFasNFOeIkWVka/fAAAAAWJLR0QAiAUd'.
     80            'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEHd'.
     81            'ceT+8AAABtSURBVHjaVchbAkMwEAXQq6i3VrQiQfa/zDYTw8z5'.
     82            'PCjGt9JVWFt1XWPh1fWNdfDy+tq6WPfRUPENNKnSnXNWPB4uv2'.
     83            'b54nSZ8jHrMtOxvWZZZtpD4KP6xLkO9/AhzhaCOMhJh68cOjzV'.
     84            '/K/4Ac2cG+nBcaRuAAAAAElFTkSuQmCC' ;
    8585
    86         //==========================================================
    87         //sq_pink.png
    88         //==========================================================
    89         $this->imgdata[4][0]= 445 ;
    90         $this->imgdata[4][1]=
    91      'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAApV'.
    92      'BMVEX////6+Pz69/v49Pr38/r17/jr4+/l3Onj2efh1ua/L+i+'.
    93      'q8m+Lue9Lua8qsS8LuW8LeS7pca5LOG4LN+2Y9O2YNW1ZdO1Kt'.
    94      'y0atC0aNGzb82zbc6zKtuzKdqycsuwa8qtJtOISZ2GRpuFN6GE'.
    95      'NqCDQpmCMZ+BPpd/LJ1/K519S5B9Jpx9Jpt9JZt6RY11BJZ1BJ'.
    96      'V0BJV0BJRzBJNvNoRtIoJUEmdZ/XbrAAAAAWJLR0QAiAUdSAAA'.
    97      'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYDF3iKMD'.
    98      'YAAACeSURBVHjaVczbEoIgGARgCiMtrexoWpaa2FHUgvd/tH4Y'.
    99      'BnEvv9ldhNPradPnnGBUTtPDzMRPSIF46SaBoR25dYjz3I20Lb'.
    100      'ek6BgQz73Il7KKpSgCO0pTHU0886J1sCe0ZYbALjGhjFnEM2es'.
    101      'VhZVI4d+B1QtfnV47ywCEaKeP/p7JdLejSYt0j6NIiOq1wJZIs'.
    102      'QTDA0ELHwhPBCwyR/Cni9cOmzJtwAAAABJRU5ErkJggg==' ;
     86//==========================================================
     87//sq_pink.png
     88//==========================================================
     89        $this->imgdata[4][0]= 445 ;
     90        $this->imgdata[4][1]=
     91            'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAApV'.
     92            'BMVEX////6+Pz69/v49Pr38/r17/jr4+/l3Onj2efh1ua/L+i+'.
     93            'q8m+Lue9Lua8qsS8LuW8LeS7pca5LOG4LN+2Y9O2YNW1ZdO1Kt'.
     94            'y0atC0aNGzb82zbc6zKtuzKdqycsuwa8qtJtOISZ2GRpuFN6GE'.
     95            'NqCDQpmCMZ+BPpd/LJ1/K519S5B9Jpx9Jpt9JZt6RY11BJZ1BJ'.
     96            'V0BJV0BJRzBJNvNoRtIoJUEmdZ/XbrAAAAAWJLR0QAiAUdSAAA'.
     97            'AAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYDF3iKMD'.
     98            'YAAACeSURBVHjaVczbEoIgGARgCiMtrexoWpaa2FHUgvd/tH4Y'.
     99            'BnEvv9ldhNPradPnnGBUTtPDzMRPSIF46SaBoR25dYjz3I20Lb'.
     100            'ek6BgQz73Il7KKpSgCO0pTHU0886J1sCe0ZYbALjGhjFnEM2es'.
     101            'VhZVI4d+B1QtfnV47ywCEaKeP/p7JdLejSYt0j6NIiOq1wJZIs'.
     102            'QTDA0ELHwhPBCwyR/Cni9cOmzJtwAAAABJRU5ErkJggg==' ;
    103103
    104         //==========================================================
    105         //sq_blue.png
    106         //==========================================================
    107         $this->imgdata[5][0]= 283 ;
    108         $this->imgdata[5][1]=
    109      'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAQl'.
    110      'BMVEX////4+fz39/z19vvy8vru7/ni4+7g4fHW1ue8vteXmt6B'.
    111      'hdhiZ7FQVaZETcxCSJo1Oq4zNoMjKakhJHcKFaMEC2jRVYdWAA'.
    112      'AAAWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0'.
    113      'SU1FB9MDCxYDN0PkEP4AAABfSURBVHjaVchHAoAgDATAVcCCIF'.
    114      'j4/1elJEjmOFDHKVgDv4iz640gLs+LMF6ZUv/VqcXXplU7Gqpy'.
    115      'PFzBT5qml9NzlOX259riWHlS4kOffviHD8PQYZx2EFMPRkw+9Q'.
    116      'FSnRPeWEDzKAAAAABJRU5ErkJggg==' ;
     104//==========================================================
     105//sq_blue.png
     106//==========================================================
     107        $this->imgdata[5][0]= 283 ;
     108        $this->imgdata[5][1]=
     109            'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAQl'.
     110            'BMVEX////4+fz39/z19vvy8vru7/ni4+7g4fHW1ue8vteXmt6B'.
     111            'hdhiZ7FQVaZETcxCSJo1Oq4zNoMjKakhJHcKFaMEC2jRVYdWAA'.
     112            'AAAWJLR0QAiAUdSAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0'.
     113            'SU1FB9MDCxYDN0PkEP4AAABfSURBVHjaVchHAoAgDATAVcCCIF'.
     114            'j4/1elJEjmOFDHKVgDv4iz640gLs+LMF6ZUv/VqcXXplU7Gqpy'.
     115            'PFzBT5qml9NzlOX259riWHlS4kOffviHD8PQYZx2EFMPRkw+9Q'.
     116            'FSnRPeWEDzKAAAAABJRU5ErkJggg==' ;
    117117
    118         //==========================================================
    119         //sq_green.png
    120         //==========================================================
    121         $this->imgdata[6][0]= 325 ;
    122         $this->imgdata[6][1]=
    123      'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'.
    124      'BMVEX////2+vX1+vX1+fT0+fPz+PPx9/Dv9u7u9e3h7uHe697a'.
    125      '6dnO2s3I1sa10LOvza2ay5aEwYBWlE9TqE5Tkk1RkEpMrUJMg0'.
    126      'hKiUNGpEFBojw8oTcsbScaYBMWlwmMT0NtAAAAAWJLR0QAiAUd'.
    127      'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEFd'.
    128      'nFx90AAABuSURBVHjaVc9HAoAgDADB2HuJWLDx/2cKBITscW4L'.
    129      '5byzMIWtZobNDZIZtrcCGZsRQ8GwvRSRNxIiMuysODKG3alikl'.
    130      'ueOPlpKTLBaRmOZxQxaXlfb5ZWI9om4WntrXiDSJzp7SBkwMQa'.
    131      'FEy0VR/NAB2kNuj7rgAAAABJRU5ErkJggg==' ;
     118//==========================================================
     119//sq_green.png
     120//==========================================================
     121        $this->imgdata[6][0]= 325 ;
     122        $this->imgdata[6][1]=
     123            'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAXV'.
     124            'BMVEX////2+vX1+vX1+fT0+fPz+PPx9/Dv9u7u9e3h7uHe697a'.
     125            '6dnO2s3I1sa10LOvza2ay5aEwYBWlE9TqE5Tkk1RkEpMrUJMg0'.
     126            'hKiUNGpEFBojw8oTcsbScaYBMWlwmMT0NtAAAAAWJLR0QAiAUd'.
     127            'SAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEFd'.
     128            'nFx90AAABuSURBVHjaVc9HAoAgDADB2HuJWLDx/2cKBITscW4L'.
     129            '5byzMIWtZobNDZIZtrcCGZsRQ8GwvRSRNxIiMuysODKG3alikl'.
     130            'ueOPlpKTLBaRmOZxQxaXlfb5ZWI9om4WntrXiDSJzp7SBkwMQa'.
     131            'FEy0VR/NAB2kNuj7rgAAAABJRU5ErkJggg==' ;
    132132
    133         //==========================================================
    134         //sq_orange.png
    135         //==========================================================
    136         $this->imgdata[7][0]= 321 ;
    137         $this->imgdata[7][1]=
    138      'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAUV'.
    139      'BMVEX/////8+n/8uf/8OP/59H/5Mv/zqH/zJ3/ypv/yJf/vYH/'.
    140      'u33/uXn/n0n/nUX/m0H/lzn/ljf/lDP/kS3/kCv/iR//hxv/fg'.
    141      'n/fAX/eQDYZgDW6ia5AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAL'.
    142      'EgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEJIgbx+cAAAB2SURBVH'.
    143      'jaVczRCoQwDETRbLAWLZSGUA35/w/dVI0283i4DODew3YESmWW'.
    144      'kg5gWkoQAe6TleUQI/66Sy7i56+kLk7cht2N0+hcnJgQu0SqiC'.
    145      '1SzSIbzWSi6gavqJ63wSduRi2f+kwyD5rEukwCdZ1kGAMGMfv9'.
    146      'AbWuGMOr5COSAAAAAElFTkSuQmCC' ;
     133//==========================================================
     134//sq_orange.png
     135//==========================================================
     136        $this->imgdata[7][0]= 321 ;
     137        $this->imgdata[7][1]=
     138            'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAAUV'.
     139            'BMVEX/////8+n/8uf/8OP/59H/5Mv/zqH/zJ3/ypv/yJf/vYH/'.
     140            'u33/uXn/n0n/nUX/m0H/lzn/ljf/lDP/kS3/kCv/iR//hxv/fg'.
     141            'n/fAX/eQDYZgDW6ia5AAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAL'.
     142            'EgAACxIB0t1+/AAAAAd0SU1FB9MDCxYEJIgbx+cAAAB2SURBVH'.
     143            'jaVczRCoQwDETRbLAWLZSGUA35/w/dVI0283i4DODew3YESmWW'.
     144            'kg5gWkoQAe6TleUQI/66Sy7i56+kLk7cht2N0+hcnJgQu0SqiC'.
     145            '1SzSIbzWSi6gavqJ63wSduRi2f+kwyD5rEukwCdZ1kGAMGMfv9'.
     146            'AbWuGMOr5COSAAAAAElFTkSuQmCC' ;
    147147    }
    148148}
  • trunk/client/modules/Elezioni/grafici/imgdata_stars.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        IMGDATA_STARS.INC
    4 // Description: Base64 encoded images for stars
    5 // Created:     2003-03-20
    6 // Ver:         $Id: imgdata_stars.inc.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        IMGDATA_STARS.INC
     4// Description: Base64 encoded images for stars
     5// Created:     2003-03-20
     6// Ver:         $Id: imgdata_stars.inc.php 860 2007-03-23 19:16:19Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    1515
    1616    protected $colors = array('bluegreen','lightblue','purple','blue','green','pink','red','yellow');
    17     protected $index  = array('bluegreen'=>3,'lightblue'=>4,'purple'=>1,
    18    'blue'=>5,'green'=>0,'pink'=>7,'red'=>2,'yellow'=>6);
     17    protected $index  = array('bluegreen'=>3,'lightblue'=>4,'purple'=>1, 
     18                        'blue'=>5,'green'=>0,'pink'=>7,'red'=>2,'yellow'=>6);
    1919    protected $maxidx = 7 ;
    2020    protected $imgdata ;
    2121
    22     function __construct() {
    23         //==========================================================
    24         // File: bstar_green_001.png
    25         //==========================================================
    26         $this->imgdata[0][0]= 329 ;
    27         $this->imgdata[0][1]=
    28      'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAAUV'.
    29      'BMVEX///////+/v7+83rqcyY2Q/4R7/15y/1tp/05p/0lg/zdX'.
    30      '/zdX/zVV/zdO/zFJ9TFJvDFD4yg+8Bw+3iU68hwurhYotxYosx'.
    31      'YokBoTfwANgQFUp7DWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
    32      'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJj'.
    33      'CRyxgTAAAAcUlEQVR4nH3MSw6AIAwEUBL/IKBWwXL/g0pLojUS'.
    34      'ZzGLl8ko9Zumhr5iy66/GH0dp49llNPB5sTotDY5PVuLG6tnM9'.
    35      'CVKSIe1joSgPsAKSuANNaENFQvTAGzmheSkUpMBWeJZwqBT8wo'.
    36      'hmysD4bnnPsC/x8ItUdGPfAAAAAASUVORK5CYII=' ;
    37         //==========================================================
    38         // File: bstar_blred.png
    39         //==========================================================
    40         $this->imgdata[1][0]= 325 ;
    41         $this->imgdata[1][1]=
    42      'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
    43      'BMVEX///+/v79uRJ6jWPOSUtKrb+ejWO+gWPaGTruJTr6rZvF2'.
    44      'RqC2ocqdVuCeV+egV/GsnLuIXL66rMSpcOyATbipY/OdWOp+VK'.
    45      'aTU9WhV+yJKBoLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
    46      'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJwynv1'.
    47      'XVAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
    48      'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
    49      'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
    50      'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
     22    function ImgData_Stars() {
     23//==========================================================
     24// File: bstar_green_001.png
     25//==========================================================
     26        $this->imgdata[0][0]= 329 ;
     27        $this->imgdata[0][1]=
     28            'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAAUV'.
     29            'BMVEX///////+/v7+83rqcyY2Q/4R7/15y/1tp/05p/0lg/zdX'.
     30            '/zdX/zVV/zdO/zFJ9TFJvDFD4yg+8Bw+3iU68hwurhYotxYosx'.
     31            'YokBoTfwANgQFUp7DWAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgF'.
     32            'HUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJj'.
     33            'CRyxgTAAAAcUlEQVR4nH3MSw6AIAwEUBL/IKBWwXL/g0pLojUS'.
     34            'ZzGLl8ko9Zumhr5iy66/GH0dp49llNPB5sTotDY5PVuLG6tnM9'.
     35            'CVKSIe1joSgPsAKSuANNaENFQvTAGzmheSkUpMBWeJZwqBT8wo'.
     36            'hmysD4bnnPsC/x8ItUdGPfAAAAAASUVORK5CYII=' ;
     37//==========================================================
     38// File: bstar_blred.png
     39//==========================================================
     40        $this->imgdata[1][0]= 325 ;
     41        $this->imgdata[1][1]=
     42            'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
     43            'BMVEX///+/v79uRJ6jWPOSUtKrb+ejWO+gWPaGTruJTr6rZvF2'.
     44            'RqC2ocqdVuCeV+egV/GsnLuIXL66rMSpcOyATbipY/OdWOp+VK'.
     45            'aTU9WhV+yJKBoLAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
     46            'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJwynv1'.
     47            'XVAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
     48            'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
     49            'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
     50            'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
    5151
    52         //==========================================================
    53         // File: bstar_red_001.png
    54         //==========================================================
    55         $this->imgdata[2][0]= 325 ;
    56         $this->imgdata[2][1]=
    57      'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
    58      'BMVEX///+/v7+eRFHzWG3SUmHnb37vWGr2WHG7Tlm+TljxZneg'.
    59      'Rk3KoaXgVmXnV2nxV227nJ++XGzErK3scIS4TVzzY3fqWG2mVF'.
    60      'zVU2PsV2rJFw9VAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
    61      'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJzCI0C'.
    62      'lSAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
    63      'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
    64      'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
    65      'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
     52//==========================================================
     53// File: bstar_red_001.png
     54//==========================================================
     55        $this->imgdata[2][0]= 325 ;
     56        $this->imgdata[2][1]=
     57            'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
     58            'BMVEX///+/v7+eRFHzWG3SUmHnb37vWGr2WHG7Tlm+TljxZneg'.
     59            'Rk3KoaXgVmXnV2nxV227nJ++XGzErK3scIS4TVzzY3fqWG2mVF'.
     60            'zVU2PsV2rJFw9VAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
     61            'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJzCI0C'.
     62            'lSAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
     63            'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
     64            'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
     65            'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
    6666
    67         //==========================================================
    68         // File: bstar_blgr_001.png
    69         //==========================================================
    70         $this->imgdata[3][0]= 325 ;
    71         $this->imgdata[3][1]=
    72      'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
    73      'BMVEX///+/v79Ehp5Yx/NSq9Jvw+dYwu9YzfZOmbtOmb5myPFG'.
    74      'gqChvcpWteBXvedXxvGcsbtcpb6su8RwzOxNmrhjyvNYwupUjK'.
    75      'ZTr9VXwOyJhmWNAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
    76      'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJTC65k'.
    77      'vQAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
    78      'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
    79      'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
    80      'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
     67//==========================================================
     68// File: bstar_blgr_001.png
     69//==========================================================
     70        $this->imgdata[3][0]= 325 ;
     71        $this->imgdata[3][1]=
     72            'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
     73            'BMVEX///+/v79Ehp5Yx/NSq9Jvw+dYwu9YzfZOmbtOmb5myPFG'.
     74            'gqChvcpWteBXvedXxvGcsbtcpb6su8RwzOxNmrhjyvNYwupUjK'.
     75            'ZTr9VXwOyJhmWNAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
     76            'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJTC65k'.
     77            'vQAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
     78            'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
     79            'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
     80            'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
    8181
    82         //==========================================================
    83         // File: bstar_blgr_002.png
    84         //==========================================================
    85         $this->imgdata[4][0]= 325 ;
    86         $this->imgdata[4][1]=
    87      'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
    88      'BMVEX///+/v79EnpxY8/FS0dJv5+dY7+9Y9vBOubtOur5m8fFG'.
    89      'nKChycpW3uBX5+ZX8e2curtcvrqswsRw7OdNuLZj8/BY6udUpK'.
    90      'ZT1dRX7OtNkrW5AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
    91      'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJgXHeN'.
    92      'wwAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
    93      'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
    94      'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
    95      'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
     82//==========================================================
     83// File: bstar_blgr_002.png
     84//==========================================================
     85        $this->imgdata[4][0]= 325 ;
     86        $this->imgdata[4][1]=
     87            'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
     88            'BMVEX///+/v79EnpxY8/FS0dJv5+dY7+9Y9vBOubtOur5m8fFG'.
     89            'nKChycpW3uBX5+ZX8e2curtcvrqswsRw7OdNuLZj8/BY6udUpK'.
     90            'ZT1dRX7OtNkrW5AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
     91            'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJgXHeN'.
     92            'wwAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
     93            'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
     94            'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
     95            'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
    9696
    97         //==========================================================
    98         // File: bstar_blue_001.png
    99         //==========================================================
    100         $this->imgdata[5][0]= 325 ;
    101         $this->imgdata[5][1]=
    102      'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
    103      'BMVEX///+/v79EY55Yi/NSetJvledYiO9YkPZOb7tObr5mkvFG'.
    104      'X6ChrcpWgOBXhedXi/Gcpbtcf76sssRwnOxNcbhjk/NYiepUbK'.
    105      'ZTfdVXh+ynNEzzAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
    106      'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJhStyP'.
    107      'zCAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
    108      'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
    109      'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
    110      'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
     97//==========================================================
     98// File: bstar_blue_001.png
     99//==========================================================
     100        $this->imgdata[5][0]= 325 ;
     101        $this->imgdata[5][1]=
     102            'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
     103            'BMVEX///+/v79EY55Yi/NSetJvledYiO9YkPZOb7tObr5mkvFG'.
     104            'X6ChrcpWgOBXhedXi/Gcpbtcf76sssRwnOxNcbhjk/NYiepUbK'.
     105            'ZTfdVXh+ynNEzzAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
     106            'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJhStyP'.
     107            'zCAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
     108            'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
     109            'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
     110            'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
    111111
    112         //==========================================================
    113         // File: bstar_oy_007.png
    114         //==========================================================
    115         $this->imgdata[6][0]= 325 ;
    116         $this->imgdata[6][1]=
    117      'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
    118      'BMVEX///+/v7+ejUTz11jSvVLn02/v1lj21li7q06+r07x2mag'.
    119      'lUbKxKHgy1bnz1fx1Ve7t5y+qlzEwqzs03C4pE3z2WPqz1imml'.
    120      'TVv1Ps01dGRjeyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
    121      'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJjsGGc'.
    122      'GbAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
    123      'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
    124      'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
    125      'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
     112//==========================================================
     113// File: bstar_oy_007.png
     114//==========================================================
     115        $this->imgdata[6][0]= 325 ;
     116        $this->imgdata[6][1]=
     117            'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
     118            'BMVEX///+/v7+ejUTz11jSvVLn02/v1lj21li7q06+r07x2mag'.
     119            'lUbKxKHgy1bnz1fx1Ve7t5y+qlzEwqzs03C4pE3z2WPqz1imml'.
     120            'TVv1Ps01dGRjeyAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
     121            'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJjsGGc'.
     122            'GbAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
     123            'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
     124            'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
     125            'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
    126126
    127         //==========================================================
    128         // File: bstar_lred.png
    129         //==========================================================
    130         $this->imgdata[7][0]= 325 ;
    131         $this->imgdata[7][1]=
    132      'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
    133      'BMVEX///+/v7+eRJPzWN3SUr7nb9TvWNj2WOS7Tqi+TqnxZtyg'.
    134      'Ro/KocPgVsjnV9LxV927nLa+XLTErL7scN24TarzY9/qWNemVJ'.
    135      'jVU8LsV9VCwcc9AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
    136      'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJxi9ZY'.
    137      'GoAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
    138      'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
    139      'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
    140      'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
     127//==========================================================
     128// File: bstar_lred.png
     129//==========================================================
     130        $this->imgdata[7][0]= 325 ;
     131        $this->imgdata[7][1]=
     132            'iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAMAAABsDg4iAAAATl'.
     133            'BMVEX///+/v7+eRJPzWN3SUr7nb9TvWNj2WOS7Tqi+TqnxZtyg'.
     134            'Ro/KocPgVsjnV9LxV927nLa+XLTErL7scN24TarzY9/qWNemVJ'.
     135            'jVU8LsV9VCwcc9AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgA'.
     136            'AAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTAxYTJxi9ZY'.
     137            'GoAAAAcElEQVR4nH3MyQ6AIAwEUFIqiwju2///qLQmWiJxDnN4'.
     138            'mYxSv5lqGCs2nvaLLtZx/VhGOW1MjnPJWp0zsw2wsUY2jd09BY'.
     139            'DFmESC+BwA5UCUxhqAhqrA4CGrLpCMVGK4sZe4B+/5RLdiyMb6'.
     140            'on/PuS9CdQNC7yBXEQAAAABJRU5ErkJggg==' ;
    141141    }
    142142}
  • trunk/client/modules/Elezioni/grafici/jpg-config.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPG-CONFIG.INC
    4 // Description: Configuration file for JpGraph library
    5 // Created:     2004-03-27
    6 // Ver:         $Id: jpg-config.inc.php 1871 2009-09-29 05:56:39Z ljp $
    7 //
    8 // Copyright (c) Asial Corporation. All rights reserved.
     3// File:        JPG-CONFIG.INC
     4// Description: Configuration file for JpGraph library
     5// Created:     2004-03-27
     6// Ver:         $Id: jpg-config.inc.php 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
    1111
    12 //------------------------------------------------------------------------
    13 // Directories for cache and font directory.
     12
     13//------------------------------------------------------------------------
     14// Directories for cache and font directory.
    1415//
    1516// CACHE_DIR:
     
    2829//   CACHE_DIR /tmp/jpgraph_cache/
    2930//   TTF_DIR   /usr/share/fonts/truetype/
    30 //   MBTTF_DIR /usr/share/fonts/truetype/
    31 //
     31//   MBTTF_DIR /usr/share/fonts/ja/TrueType/
     32//
     33define("TTF_DIR","/usr/share/fonts/truetype/ttf-dejavu/");
    3234// WINDOWS:
    3335//   CACHE_DIR $SERVER_TEMP/jpgraph_cache/
     
    3638//
    3739//------------------------------------------------------------------------
    38 // define('CACHE_DIR','/tmp/jpgraph_cache/');
    39 // define('TTF_DIR','/usr/share/fonts/TrueType/');
    40 // define('MBTTF_DIR','/usr/share/fonts/TrueType/');
     40// define("CACHE_DIR","/tmp/jpgraph_cache/");
     41// define("TTF_DIR","/usr/share/fonts/truetype/");
     42// define("MBTTF_DIR","/usr/share/fonts/ja/TrueType/");
    4143
    4244//-------------------------------------------------------------------------
     
    4446// using the cache.
    4547// The directory must be the filesysystem name as seen by PHP
    46 // and the 'http' version must be the same directory but as
    47 // seen by the HTTP server relative to the 'htdocs' ddirectory.
     48// and the 'http' version must be the same directory but as 
     49// seen by the HTTP server relative to the 'htdocs' ddirectory. 
    4850// If a relative path is specified it is taken to be relative from where
    4951// the image script is executed.
    50 // Note: The default setting is to create a subdirectory in the
     52// Note: The default setting is to create a subdirectory in the 
    5153// directory from where the image script is executed and store all files
    5254// there. As ususal this directory must be writeable by the PHP process.
    53 define('CSIMCACHE_DIR','csimcache/');
    54 define('CSIMCACHE_HTTP_DIR','csimcache/');
     55define("CSIMCACHE_DIR","csimcache/");
     56define("CSIMCACHE_HTTP_DIR","csimcache/");
     57
     58//------------------------------------------------------------------------
     59// Defines for font setup
     60//------------------------------------------------------------------------
     61
     62// Actual name of the TTF file used together with FF_CHINESE aka FF_BIG5
     63// This is the TTF file being used when the font family is specified as
     64// either FF_CHINESE or FF_BIG5
     65define('CHINESE_TTF_FONT','bkai00mp.ttf');
     66
     67// Special unicode greek language support
     68define("LANGUAGE_GREEK",false);
     69
     70// If you are setting this config to true the conversion of greek characters
     71// will assume that the input text is windows 1251
     72define("GREEK_FROM_WINDOWS",false);
     73
     74// Special unicode cyrillic language support
     75define("LANGUAGE_CYRILLIC",false);
     76
     77// If you are setting this config to true the conversion
     78// will assume that the input text is windows 1251, if
     79// false it will assume koi8-r
     80define("CYRILLIC_FROM_WINDOWS",false);
     81
     82// The following constant is used to auto-detect
     83// whether cyrillic conversion is really necessary
     84// if enabled. Just replace 'windows-1251' with a variable
     85// containing the input character encoding string
     86// of your application calling jpgraph.
     87// A typical such string would be 'UTF-8' or 'utf-8'.
     88// The comparison is case-insensitive.
     89// If this charset is not a 'koi8-r' or 'windows-1251'
     90// derivate then no conversion is done.
     91//
     92// This constant can be very important in multi-user
     93// multi-language environments where a cyrillic conversion
     94// could be needed for some cyrillic people
     95// and resulting in just erraneous conversions
     96// for not-cyrillic language based people.
     97//
     98// Example: In the free project management
     99// software dotproject.net $locale_char_set is dynamically
     100// set by the language environment the user has chosen.
     101//
     102// Usage: define('LANGUAGE_CHARSET', $locale_char_set);
     103//
     104// where $locale_char_set is a GLOBAL (string) variable
     105// from the application including JpGraph.
     106//
     107define('LANGUAGE_CHARSET', null);
     108
     109// Japanese TrueType font used with FF_MINCHO, FF_PMINCHO, FF_GOTHIC, FF_PGOTHIC
     110define('MINCHO_TTF_FONT','ipam.ttf');
     111define('PMINCHO_TTF_FONT','ipamp.ttf');
     112define('GOTHIC_TTF_FONT','ipag.ttf');
     113define('PGOTHIC_TTF_FONT','ipagp.ttf');
     114
     115// Assume that Japanese text have been entered in EUC-JP encoding.
     116// If this define is true then conversion from EUC-JP to UTF8 is done
     117// automatically in the library using the mbstring module in PHP.
     118define('ASSUME_EUCJP_ENCODING',false);
    55119
    56120//------------------------------------------------------------------------
     
    64128define('DEFAULT_ERR_LOCALE','en');
    65129
    66 // Deafult graphic format set to 'auto' which will automatically
     130// Deafult graphic format set to "auto" which will automatically
    67131// choose the best available format in the order png,gif,jpeg
    68132// (The supported format depends on what your PHP installation supports)
    69 define('DEFAULT_GFORMAT','auto');
     133define("DEFAULT_GFORMAT","auto");
    70134
    71135// Should the cache be used at all? By setting this to false no
    72 // files will be generated in the cache directory.
     136// files will be generated in the cache directory. 
    73137// The difference from READ_CACHE being that setting READ_CACHE to
    74138// false will still create the image in the cache directory
    75139// just not use it. By setting USE_CACHE=false no files will even
    76140// be generated in the cache directory.
    77 define('USE_CACHE',false);
    78 
    79 // Should we try to find an image in the cache before generating it?
     141define("USE_CACHE",false);
     142
     143// Should we try to find an image in the cache before generating it? 
    80144// Set this define to false to bypass the reading of the cache and always
    81 // regenerate the image. Note that even if reading the cache is
     145// regenerate the image. Note that even if reading the cache is 
    82146// disabled the cached will still be updated with the newly generated
    83 // image. Set also 'USE_CACHE' below.
    84 define('READ_CACHE',true);
     147// image. Set also "USE_CACHE" below.
     148define("READ_CACHE",true);
    85149
    86150// Determine if the error handler should be image based or purely
    87151// text based. Image based makes it easier since the script will
    88152// always return an image even in case of errors.
    89 define('USE_IMAGE_ERROR_HANDLER',true);
    90 
    91 // Should the library examine the global php_errmsg string and convert
     153define("USE_IMAGE_ERROR_HANDLER",true);
     154
     155// Should the library examin the global php_errmsg string and convert
    92156// any error in it to a graphical representation. This is handy for the
    93157// occasions when, for example, header files cannot be found and this results
    94 // in the graph not being created and just a 'red-cross' image would be seen.
     158// in the graph not being created and just a "red-cross" image would be seen.
    95159// This should be turned off for a production site.
    96 define('CATCH_PHPERRMSG',true);
     160define("CATCH_PHPERRMSG",true);
    97161
    98162// Determine if the library should also setup the default PHP
    99163// error handler to generate a graphic error mesage. This is useful
    100164// during development to be able to see the error message as an image
    101 // instead as a 'red-cross' in a page where an image is expected.
    102 define('INSTALL_PHP_ERR_HANDLER',false);
     165// instead as a "red-cross" in a page where an image is expected.
     166define("INSTALL_PHP_ERR_HANDLER",false);
     167
     168// If the color palette is full should JpGraph try to allocate
     169// the closest match? If you plan on using background images or
     170// gradient fills it might be a good idea to enable this.
     171// If not you will otherwise get an error saying that the color palette is
     172// exhausted. The drawback of using approximations is that the colors
     173// might not be exactly what you specified.
     174// Note1: This does only apply to paletted images, not truecolor
     175// images since they don't have the limitations of maximum number
     176// of colors.
     177define("USE_APPROX_COLORS",true);
    103178
    104179// Should usage of deprecated functions and parameters give a fatal error?
    105180// (Useful to check if code is future proof.)
    106 define('ERR_DEPRECATED',true);
    107 
    108 // The builtin GD function imagettfbbox() fuction which calculates the bounding box for
    109 // text using TTF fonts is buggy. By setting this define to true the library
    110 // uses its own compensation for this bug. However this will give a
    111 // slightly different visual apparance than not using this compensation.
    112 // Enabling this compensation will in general give text a bit more space to more
    113 // truly reflect the actual bounding box which is a bit larger than what the
    114 // GD function thinks.
    115 define('USE_LIBRARY_IMAGETTFBBOX',true);
     181define("ERR_DEPRECATED",true);
     182
     183// Should the time taken to generate each picture be branded to the lower
     184// left in corner in each generated image? Useful for performace measurements
     185// generating graphs
     186define("BRAND_TIMING",false);
     187
     188// What format should be used for the timing string?
     189define("BRAND_TIME_FORMAT","(%01.3fs)");
    116190
    117191//------------------------------------------------------------------------
     
    120194
    121195// What group should the cached file belong to
    122 // (Set to '' will give the default group for the 'PHP-user')
     196// (Set to "" will give the default group for the "PHP-user")
    123197// Please note that the Apache user must be a member of the
    124198// specified group since otherwise it is impossible for Apache
    125199// to set the specified group.
    126 define('CACHE_FILE_GROUP','www');
     200define("CACHE_FILE_GROUP","wwwadmin");
    127201
    128202// What permissions should the cached file have
    129 // (Set to '' will give the default persmissions for the 'PHP-user')
    130 define('CACHE_FILE_MOD',0664);
    131 
    132 // Default theme class name
    133 define('DEFAULT_THEME_CLASS', 'UniversalTheme');
    134 
    135 define('SUPERSAMPLING', true);
    136 define('SUPERSAMPLING_SCALE', 1);
     203// (Set to "" will give the default persmissions for the "PHP-user")
     204define("CACHE_FILE_MOD",0664);
     205
     206// Decide if we should use the bresenham circle algorithm or the
     207// built in Arc(). Bresenham gives better visual apperance of circles
     208// but is more CPU intensive and slower then the built in Arc() function
     209// in GD. Turned off by default for speed
     210define("USE_BRESENHAM",false);
     211
     212// Special file name to indicate that we only want to calc
     213// the image map in the call to Graph::Stroke() used
     214// internally from the GetHTMLCSIM() method.
     215define("_CSIM_SPECIALFILE","_csim_special_");
     216
     217// HTTP GET argument that is used with image map
     218// to indicate to the script to just generate the image
     219// and not the full CSIM HTML page.
     220define("_CSIM_DISPLAY","_jpg_csimd");
     221
     222// Special filename for Graph::Stroke(). If this filename is given
     223// then the image will NOT be streamed to browser of file. Instead the
     224// Stroke call will return the handler for the created GD image.
     225define("_IMG_HANDLER","__handle");
     226
    137227
    138228?>
  • trunk/client/modules/Elezioni/grafici/jpgraph.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH.PHP
    4 // Description: PHP Graph Plotting library. Base module.
    5 // Created:     2001-01-08
    6 // Ver:         $Id: jpgraph.php 1924 2010-01-11 14:03:26Z ljp $
     3// File:        JPGRAPH.PHP
     4// Description: PHP Graph Plotting library. Base module.
     5// Created:     2001-01-08
     6// Ver:         $Id: jpgraph.php 1091 2009-01-18 22:57:40Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    1616require_once('jpgraph_text.inc.php');
    1717require_once('jpgraph_legend.inc.php');
    18 require_once('jpgraph_theme.inc.php');
    19 require_once('gd_image.inc.php');
    2018
    2119// Version info
    22 define('JPG_VERSION','4.2.6');
     20define('JPG_VERSION','2.3.5-dev');
    2321
    2422// Minimum required PHP version
    2523define('MIN_PHPVERSION','5.1.0');
    2624
    27 // Special file name to indicate that we only want to calc
    28 // the image map in the call to Graph::Stroke() used
    29 // internally from the GetHTMLCSIM() method.
    30 define('_CSIM_SPECIALFILE','_csim_special_');
    31 
    32 // HTTP GET argument that is used with image map
    33 // to indicate to the script to just generate the image
    34 // and not the full CSIM HTML page.
    35 define('_CSIM_DISPLAY','_jpg_csimd');
    36 
    37 // Special filename for Graph::Stroke(). If this filename is given
    38 // then the image will NOT be streamed to browser of file. Instead the
    39 // Stroke call will return the handler for the created GD image.
    40 define('_IMG_HANDLER','__handle');
    41 
    42 // Special filename for Graph::Stroke(). If this filename is given
    43 // the image will be stroked to a file with a name based on the script name.
    44 define('_IMG_AUTO','auto');
     25// Should the image be a truecolor image?
     26define('USE_TRUECOLOR',true);
     27
     28//------------------------------------------------------------------------
     29// Automatic settings of path for cache and font directory
     30// if they have not been previously specified
     31//------------------------------------------------------------------------
     32if(USE_CACHE) {
     33    if (!defined('CACHE_DIR')) {
     34        if ( strstr( PHP_OS, 'WIN') ) {
     35            if( empty($_SERVER['TEMP']) ) {
     36                $t = new ErrMsgText();
     37                $msg = $t->Get(11,$file,$lineno);
     38                die($msg);
     39            }
     40            else {
     41                define('CACHE_DIR', $_SERVER['TEMP'] . '/');
     42            }
     43        } else {
     44            define('CACHE_DIR','/tmp/jpgraph_cache/');
     45        }
     46    }
     47}
     48elseif( !defined('CACHE_DIR') ) {
     49    define('CACHE_DIR', '');
     50}
     51
     52if (!defined('TTF_DIR')) {
     53    if (strstr( PHP_OS, 'WIN') ) {
     54        $sroot = getenv('SystemRoot');
     55        if( empty($sroot) ) {
     56            $t = new ErrMsgText();
     57            $msg = $t->Get(12,$file,$lineno);
     58            die($msg);
     59        }
     60        else {
     61          define('TTF_DIR', $sroot.'/fonts/');
     62        }
     63    } else {
     64        define('TTF_DIR','/usr/share/fonts/truetype/');
     65    }
     66}
     67
     68if (!defined('MBTTF_DIR')) {
     69    if (strstr( PHP_OS, 'WIN') ) {
     70        $sroot = getenv('SystemRoot');
     71        if( empty($sroot) ) {
     72            $t = new ErrMsgText();
     73            $msg = $t->Get(12,$file,$lineno);
     74            die($msg);
     75        }
     76        else {
     77          define('TTF_DIR', $sroot.'/fonts/');
     78        }
     79    } else {
     80        define('MBTTF_DIR','/usr/share/fonts/ja/TrueType/');
     81    }
     82}
     83
     84//------------------------------------------------------------------
     85// Constants which are used as parameters for the method calls
     86//------------------------------------------------------------------
     87
    4588
    4689// Tick density
     
    5093define("TICKD_VERYSPARSE",4);
    5194
    52 // Side for ticks and labels.
     95// Side for ticks and labels. 
    5396define("SIDE_LEFT",-1);
    5497define("SIDE_RIGHT",1);
     
    113156define("HORIZONTAL",0);
    114157
     158
    115159// Axis styles for scientific style axis
    116160define('AXSTYLE_SIMPLE',1);
     
    132176define('TITLEBKG_FILLSTYLE_SOLID',3);
    133177
    134 // Styles for axis labels background
    135 define('LABELBKG_NONE',0);
    136 define('LABELBKG_XAXIS',1);
    137 define('LABELBKG_YAXIS',2);
    138 define('LABELBKG_XAXISFULL',3);
    139 define('LABELBKG_YAXISFULL',4);
    140 define('LABELBKG_XYFULL',5);
    141 define('LABELBKG_XY',6);
    142 
    143 
    144178// Style for background gradient fills
    145179define('BGRAD_FRAME',1);
     
    157191define('SKEW3D_RIGHT',3);
    158192
     193// Line styles
     194define('LINESTYLE_SOLID',1);
     195define('LINESTYLE_DOTTED',2);
     196define('LINESTYLE_DASHED',3);
     197define('LINESTYLE_LONGDASH',4);
     198
    159199// For internal use only
    160200define("_JPG_DEBUG",false);
     
    162202define("_FORCE_IMGDIR",'/tmp/jpgimg/');
    163203
    164 
    165 //
    166 // Automatic settings of path for cache and font directory
    167 // if they have not been previously specified
    168 //
    169 if(USE_CACHE) {
    170     if (!defined('CACHE_DIR')) {
    171         if ( strstr( PHP_OS, 'WIN') ) {
    172             if( empty($_SERVER['TEMP']) ) {
    173                 $t = new ErrMsgText();
    174                 $msg = $t->Get(11,$file,$lineno);
    175                 die($msg);
    176             }
    177             else {
    178                 define('CACHE_DIR', $_SERVER['TEMP'] . '/');
    179             }
    180         } else {
    181             define('CACHE_DIR','/tmp/jpgraph_cache/');
    182         }
    183     }
    184 }
    185 elseif( !defined('CACHE_DIR') ) {
    186     define('CACHE_DIR', '');
    187 }
    188 
    189 //
    190 // Setup path for western/latin TTF fonts
    191 //
    192 if (!defined('TTF_DIR')) {
    193     if (strstr( PHP_OS, 'WIN') ) {
    194         $sroot = getenv('SystemRoot');
    195         if( empty($sroot) ) {
    196             $t = new ErrMsgText();
    197             $msg = $t->Get(12,$file,$lineno);
    198             die($msg);
    199         }
    200         else {
    201             define('TTF_DIR', $sroot.'/fonts/');
    202         }
    203     } else {
    204         define('TTF_DIR','/usr/share/fonts/truetype/');
    205     }
    206 }
    207 
    208 //
    209 // Setup path for MultiByte TTF fonts (japanese, chinese etc.)
    210 //
    211 if (!defined('MBTTF_DIR')) {
    212     if (strstr( PHP_OS, 'WIN') ) {
    213         $sroot = getenv('SystemRoot');
    214         if( empty($sroot) ) {
    215             $t = new ErrMsgText();
    216             $msg = $t->Get(12,$file,$lineno);
    217             die($msg);
    218         }
    219         else {
    220             define('MBTTF_DIR', $sroot.'/fonts/');
    221         }
    222     } else {
    223         define('MBTTF_DIR','/usr/share/fonts/truetype/');
    224     }
    225 }
    226 
    227 //
    228 // Check minimum PHP version
    229 //
    230 function CheckPHPVersion($aMinVersion) {
    231     list($majorC, $minorC, $editC) = preg_split('/[\/.-]/', PHP_VERSION);
    232     list($majorR, $minorR, $editR) = preg_split('/[\/.-]/', $aMinVersion);
    233 
     204require_once('gd_image.inc.php');
     205
     206function CheckPHPVersion($aMinVersion)
     207{
     208    list($majorC, $minorC, $editC) = split('[/.-]', PHP_VERSION);
     209    list($majorR, $minorR, $editR) = split('[/.-]', $aMinVersion);
     210 
     211    if ($majorC != $majorR) return false;
    234212    if ($majorC < $majorR) return false;
    235 
    236     if ($majorC == $majorR) {
    237         if($minorC < $minorR) return false;
    238 
    239         if($minorC == $minorR){
    240             if($editC < $editR) return false;
    241         }
    242     }
    243 
     213    // same major - check ninor
     214    if ($minorC > $minorR) return true;
     215    if ($minorC < $minorR) return false;
     216    // and same minor
     217    if ($editC  >= $editR)  return true;
    244218    return true;
    245219}
     
    253227}
    254228
     229
    255230//
    256231// Make GD sanity check
     
    258233if( !function_exists("imagetypes") || !function_exists('imagecreatefromstring') ) {
    259234    JpGraphError::RaiseL(25001);
    260     //("This PHP installation is not configured with the GD library. Please recompile PHP with GD support to run JpGraph. (Neither function imagetypes() nor imagecreatefromstring() does exist)");
     235//("This PHP installation is not configured with the GD library. Please recompile PHP with GD support to run JpGraph. (Neither function imagetypes() nor imagecreatefromstring() does exist)");
    261236}
    262237
     
    267242    // Respect current error level
    268243    if( $errno & error_reporting() ) {
    269         JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg);
     244        JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg);
    270245    }
    271246}
     
    276251
    277252//
    278 // Check if there were any warnings, perhaps some wrong includes by the user. In this
    279 // case we raise it immediately since otherwise the image will not show and makes
    280 // debugging difficult. This is controlled by the user setting CATCH_PHPERRMSG
     253//Check if there were any warnings, perhaps some wrong includes by the
     254//user
    281255//
    282 if( isset($GLOBALS['php_errormsg']) && CATCH_PHPERRMSG && !preg_match('/|Deprecated|/i', $GLOBALS['php_errormsg']) ) {
     256if( isset($GLOBALS['php_errormsg']) && CATCH_PHPERRMSG &&
     257    !preg_match('/|Deprecated|/i', $GLOBALS['php_errormsg']) ) {
    283258    JpGraphError::RaiseL(25004,$GLOBALS['php_errormsg']);
    284259}
    285260
     261
    286262// Useful mathematical function
    287263function sign($a) {return $a >= 0 ? 1 : -1;}
    288264
    289 //
    290265// Utility function to generate an image name based on the filename we
    291266// are running from and assuming we use auto detection of graphic format
    292267// (top level), i.e it is safe to call this function
    293268// from a script that uses JpGraph
    294 //
    295269function GenImgName() {
    296270    // Determine what format we should use when we save the images
    297271    $supported = imagetypes();
    298     if( $supported & IMG_PNG )    $img_format="png";
     272    if( $supported & IMG_PNG )     $img_format="png";
    299273    elseif( $supported & IMG_GIF ) $img_format="gif";
    300274    elseif( $supported & IMG_JPG ) $img_format="jpeg";
     
    303277
    304278
    305     if( !isset($_SERVER['PHP_SELF']) ) {
    306         JpGraphError::RaiseL(25005);
    307         //(" Can't access PHP_SELF, PHP global variable. You can't run PHP from command line if you want to use the 'auto' naming of cache or image files.");
    308     }
     279    if( !isset($_SERVER['PHP_SELF']) )
     280        JpGraphError::RaiseL(25005);
     281//(" Can't access PHP_SELF, PHP global variable. You can't run PHP from command line if you want to use the 'auto' naming of cache or image files.");
    309282    $fname = basename($_SERVER['PHP_SELF']);
    310283    if( !empty($_SERVER['QUERY_STRING']) ) {
    311         $q = @$_SERVER['QUERY_STRING'];
    312         $fname .= '_'.preg_replace("/\W/", "_", $q).'.'.$img_format;
     284        $q = @$_SERVER['QUERY_STRING'];
     285        $fname .= '_'.preg_replace("/\W/", "_", $q).'.'.$img_format;
    313286    }
    314287    else {
    315         $fname = substr($fname,0,strlen($fname)-4).'.'.$img_format;
     288        $fname = substr($fname,0,strlen($fname)-4).'.'.$img_format;
    316289    }
    317290    return $fname;
    318291}
     292
    319293
    320294//===================================================
     
    325299//===================================================
    326300class JpgTimer {
    327     private $start, $idx;
    328 
    329     function __construct() {
    330         $this->idx=0;
    331     }
     301    private $start, $idx;       
     302//---------------
     303// CONSTRUCTOR
     304    function JpgTimer() {
     305        $this->idx=0;
     306    }
     307
     308//---------------
     309// PUBLIC METHODS       
    332310
    333311    // Push a new timer start on stack
    334312    function Push() {
    335         list($ms,$s)=explode(" ",microtime());
    336         $this->start[$this->idx++]=floor($ms*1000) + 1000*$s;
     313        list($ms,$s)=explode(" ",microtime()); 
     314        $this->start[$this->idx++]=floor($ms*1000) + 1000*$s;   
    337315    }
    338316
     
    340318    // current time
    341319    function Pop() {
    342         assert($this->idx>0);
    343         list($ms,$s)=explode(" ",microtime());
    344         $etime=floor($ms*1000) + (1000*$s);
    345         $this->idx--;
    346         return $etime-$this->start[$this->idx];
     320        assert($this->idx>0);
     321        list($ms,$s)=explode(" ",microtime()); 
     322        $etime=floor($ms*1000) + (1000*$s);
     323        $this->idx--;
     324        return $etime-$this->start[$this->idx];
    347325    }
    348326} // Class
    349327
     328$gJpgBrandTiming = BRAND_TIMING;
    350329//===================================================
    351330// CLASS DateLocale
     
    353332//===================================================
    354333class DateLocale {
    355 
     334 
    356335    public $iLocale = 'C'; // environmental locale be used by default
    357336    private $iDayAbb = null, $iShortDay = null, $iShortMonth = null, $iMonthName = null;
    358337
    359     function __construct() {
    360         settype($this->iDayAbb, 'array');
    361         settype($this->iShortDay, 'array');
    362         settype($this->iShortMonth, 'array');
    363         settype($this->iMonthName, 'array');
    364         $this->Set('C');
    365     }
    366 
     338//---------------
     339// CONSTRUCTOR 
     340    function DateLocale() {
     341        settype($this->iDayAbb, 'array');
     342        settype($this->iShortDay, 'array');
     343        settype($this->iShortMonth, 'array');
     344        settype($this->iMonthName, 'array');
     345
     346
     347        $this->Set('C');
     348    }
     349
     350//---------------
     351// PUBLIC METHODS       
    367352    function Set($aLocale) {
    368         if ( in_array($aLocale, array_keys($this->iDayAbb)) ){
    369             $this->iLocale = $aLocale;
    370             return TRUE;  // already cached nothing else to do!
    371         }
    372 
    373         $pLocale = setlocale(LC_TIME, 0); // get current locale for LC_TIME
    374 
    375         if (is_array($aLocale)) {
    376             foreach ($aLocale as $loc) {
    377                 $res = @setlocale(LC_TIME, $loc);
    378                 if ( $res ) {
    379                     $aLocale = $loc;
    380                     break;
    381                 }
    382             }
    383         }
    384         else {
    385             $res = @setlocale(LC_TIME, $aLocale);
    386         }
    387 
    388         if ( ! $res ) {
    389             JpGraphError::RaiseL(25007,$aLocale);
    390             //("You are trying to use the locale ($aLocale) which your PHP installation does not support. Hint: Use '' to indicate the default locale for this geographic region.");
    391             return FALSE;
    392         }
    393 
    394         $this->iLocale = $aLocale;
    395         for( $i = 0, $ofs = 0 - strftime('%w'); $i < 7; $i++, $ofs++ ) {
    396             $day = strftime('%a', strtotime("$ofs day"));
    397             $day[0] = strtoupper($day[0]);
    398             $this->iDayAbb[$aLocale][]= $day[0];
    399             $this->iShortDay[$aLocale][]= $day;
    400         }
    401 
    402         for($i=1; $i<=12; ++$i) {
    403             list($short ,$full) = explode('|', strftime("%b|%B",strtotime("2001-$i-01")));
    404             $this->iShortMonth[$aLocale][] = ucfirst($short);
    405             $this->iMonthName [$aLocale][] = ucfirst($full);
    406         }
    407 
    408         setlocale(LC_TIME, $pLocale);
    409 
    410         return TRUE;
     353        if ( in_array($aLocale, array_keys($this->iDayAbb)) ){
     354            $this->iLocale = $aLocale;
     355            return TRUE;  // already cached nothing else to do!
     356        }
     357
     358        $pLocale = setlocale(LC_TIME, 0); // get current locale for LC_TIME
     359
     360        if (is_array($aLocale)) {
     361            foreach ($aLocale as $loc) {
     362                $res = @setlocale(LC_TIME, $loc);
     363                if ( $res ) {
     364                    $aLocale = $loc;
     365                    break;
     366                }
     367            }
     368        }
     369        else {
     370            $res = @setlocale(LC_TIME, $aLocale);
     371        }
     372
     373        if ( ! $res ){
     374            JpGraphError::RaiseL(25007,$aLocale);
     375//("You are trying to use the locale ($aLocale) which your PHP installation does not support. Hint: Use '' to indicate the default locale for this geographic region.");
     376            return FALSE;
     377        }
     378 
     379        $this->iLocale = $aLocale;
     380        for ( $i = 0, $ofs = 0 - strftime('%w'); $i < 7; $i++, $ofs++ ){
     381            $day = strftime('%a', strtotime("$ofs day"));
     382            $day[0] = strtoupper($day[0]);
     383            $this->iDayAbb[$aLocale][]= $day[0];
     384            $this->iShortDay[$aLocale][]= $day;
     385        }
     386
     387        for($i=1; $i<=12; ++$i) {
     388            list($short ,$full) = explode('|', strftime("%b|%B",strtotime("2001-$i-01")));
     389            $this->iShortMonth[$aLocale][] = ucfirst($short);
     390            $this->iMonthName [$aLocale][] = ucfirst($full);
     391        }
     392               
     393        setlocale(LC_TIME, $pLocale);
     394
     395        return TRUE;
    411396    }
    412397
    413398
    414399    function GetDayAbb() {
    415         return $this->iDayAbb[$this->iLocale];
    416     }
    417 
     400        return $this->iDayAbb[$this->iLocale];
     401    }
     402       
    418403    function GetShortDay() {
    419         return $this->iShortDay[$this->iLocale];
     404        return $this->iShortDay[$this->iLocale];
    420405    }
    421406
    422407    function GetShortMonth() {
    423         return $this->iShortMonth[$this->iLocale];
    424     }
    425 
     408        return $this->iShortMonth[$this->iLocale];
     409    }
     410       
    426411    function GetShortMonthName($aNbr) {
    427         return $this->iShortMonth[$this->iLocale][$aNbr];
     412        return $this->iShortMonth[$this->iLocale][$aNbr];
    428413    }
    429414
    430415    function GetLongMonthName($aNbr) {
    431         return $this->iMonthName[$this->iLocale][$aNbr];
     416        return $this->iMonthName[$this->iLocale][$aNbr];
    432417    }
    433418
    434419    function GetMonth() {
    435         return $this->iMonthName[$this->iLocale];
     420        return $this->iMonthName[$this->iLocale];
    436421    }
    437422}
    438423
    439 // Global object handlers
    440424$gDateLocale = new DateLocale();
    441425$gJpgDateLocale = new DateLocale();
     
    448432    public $iLeftMargin = 3, $iRightMargin = 3, $iBottomMargin = 3 ;
    449433    public $left,$center,$right;
    450     private $iTimer=null, $itimerpoststring='';
    451 
    452     function __construct() {
    453         $this->left = new Text();
    454         $this->left->ParagraphAlign('left');
    455         $this->center = new Text();
    456         $this->center->ParagraphAlign('center');
    457         $this->right = new Text();
    458         $this->right->ParagraphAlign('right');
    459     }
    460 
    461     function SetTimer($aTimer,$aTimerPostString='') {
    462         $this->iTimer = $aTimer;
    463         $this->itimerpoststring = $aTimerPostString;
     434
     435    function Footer() {
     436        $this->left = new Text();
     437        $this->left->ParagraphAlign('left');
     438        $this->center = new Text();
     439        $this->center->ParagraphAlign('center');
     440        $this->right = new Text();
     441        $this->right->ParagraphAlign('right');
    464442    }
    465443
    466444    function SetMargin($aLeft=3,$aRight=3,$aBottom=3) {
    467         $this->iLeftMargin = $aLeft;
    468         $this->iRightMargin = $aRight;
    469         $this->iBottomMargin = $aBottom;
     445        $this->iLeftMargin = $aLeft;
     446        $this->iRightMargin = $aRight;
     447        $this->iBottomMargin = $aBottom;
    470448    }
    471449
    472450    function Stroke($aImg) {
    473         $y = $aImg->height - $this->iBottomMargin;
    474         $x = $this->iLeftMargin;
    475         $this->left->Align('left','bottom');
    476         $this->left->Stroke($aImg,$x,$y);
    477 
    478         $x = ($aImg->width - $this->iLeftMargin - $this->iRightMargin)/2;
    479         $this->center->Align('center','bottom');
    480         $this->center->Stroke($aImg,$x,$y);
    481 
    482         $x = $aImg->width - $this->iRightMargin;
    483         $this->right->Align('right','bottom');
    484         if( $this->iTimer != null ) {
    485             $this->right->Set( $this->right->t . sprintf('%.3f',$this->iTimer->Pop()/1000.0) . $this->itimerpoststring );
    486         }
    487         $this->right->Stroke($aImg,$x,$y);
     451        $y = $aImg->height - $this->iBottomMargin;
     452        $x = $this->iLeftMargin;
     453        $this->left->Align('left','bottom');
     454        $this->left->Stroke($aImg,$x,$y);
     455
     456        $x = ($aImg->width - $this->iLeftMargin - $this->iRightMargin)/2;
     457        $this->center->Align('center','bottom');
     458        $this->center->Stroke($aImg,$x,$y);
     459
     460        $x = $aImg->width - $this->iRightMargin;
     461        $this->right->Align('right','bottom');
     462        $this->right->Stroke($aImg,$x,$y);
    488463    }
    489464}
     
    495470//===================================================
    496471class Graph {
    497     public $cache=null;   // Cache object (singleton)
    498     public $img=null;   // Img object (singleton)
    499     public $plots=array();  // Array of all plot object in the graph (for Y 1 axis)
    500     public $y2plots=array();  // Array of all plot object in the graph (for Y 2 axis)
     472    public $cache=null;                 // Cache object (singleton)
     473    public $img=null;                   // Img object (singleton)
     474    public $plots=array();              // Array of all plot object in the graph (for Y 1 axis)
     475    public $y2plots=array();            // Array of all plot object in the graph (for Y 2 axis)
    501476    public $ynplots=array();
    502     public $xscale=null;  // X Scale object (could be instance of LinearScale or LogScale
     477    public $xscale=null;                // X Scale object (could be instance of LinearScale or LogScale
    503478    public $yscale=null,$y2scale=null, $ynscale=array();
    504     public $iIcons = array();  // Array of Icons to add to
    505     public $cache_name;   // File name to be used for the current graph in the cache directory
    506     public $xgrid=null;   // X Grid object (linear or logarithmic)
    507     public $ygrid=null,$y2grid=null; //dito for Y
    508     public $doframe,$frame_color, $frame_weight; // Frame around graph
    509     public $boxed=false, $box_color='black', $box_weight=1;  // Box around plot area
    510     public $doshadow=false,$shadow_width=4,$shadow_color='gray@0.5'; // Shadow for graph
    511     public $xaxis=null;   // X-axis (instane of Axis class)
    512     public $yaxis=null, $y2axis=null, $ynaxis=array(); // Y axis (instance of Axis class)
    513     public $margin_color; // Margin color of graph
    514     public $plotarea_color=array(255,255,255); // Plot area color
    515     public $title,$subtitle,$subsubtitle;  // Title and subtitle(s) text object
    516     public $axtype="linlin";  // Type of axis
    517     public $xtick_factor,$ytick_factor; // Factor to determine the maximum number of ticks depending on the plot width
    518     public $texts=null, $y2texts=null; // Text object to ge shown in the graph
     479    public $iIcons = array();           // Array of Icons to add to
     480    public $cache_name;                 // File name to be used for the current graph in the cache directory
     481    public $xgrid=null;                 // X Grid object (linear or logarithmic)
     482    public $ygrid=null,$y2grid=null;    //dito for Y
     483    public $doframe=true,$frame_color=array(0,0,0), $frame_weight=1;    // Frame around graph
     484    public $boxed=false, $box_color=array(0,0,0), $box_weight=1;                // Box around plot area
     485    public $doshadow=false,$shadow_width=4,$shadow_color=array(102,102,102);    // Shadow for graph
     486    public $xaxis=null;                 // X-axis (instane of Axis class)
     487    public $yaxis=null, $y2axis=null, $ynaxis=array();  // Y axis (instance of Axis class)
     488    public $margin_color=array(200,200,200);    // Margin color of graph
     489    public $plotarea_color=array(255,255,255);  // Plot area color
     490    public $title,$subtitle,$subsubtitle;       // Title and subtitle(s) text object
     491    public $axtype="linlin";            // Type of axis
     492    public $xtick_factor,$ytick_factor; // Factor to determine the maximum number of ticks depending on the plot width
     493    public $texts=null, $y2texts=null;  // Text object to ge shown in the graph
    519494    public $lines=null, $y2lines=null;
    520495    public $bands=null, $y2bands=null;
    521     public $text_scale_off=0, $text_scale_abscenteroff=-1; // Text scale in fractions and for centering bars
    522     public $background_image='',$background_image_type=-1,$background_image_format="png";
     496    public $text_scale_off=0, $text_scale_abscenteroff=-1;      // Text scale in fractions and for centering bars
     497    public $background_image="",$background_image_type=-1,$background_image_format="png";
    523498    public $background_image_bright=0,$background_image_contr=0,$background_image_sat=0;
    524499    public $background_image_xpos=0,$background_image_ypos=0;
     
    526501    public $inline;
    527502    public $showcsim=0,$csimcolor="red";//debug stuff, draw the csim boundaris on the image if <>0
    528     public $grid_depth=DEPTH_BACK; // Draw grid under all plots as default
     503    public $grid_depth=DEPTH_BACK;      // Draw grid under all plots as default
    529504    public $iAxisStyle = AXSTYLE_SIMPLE;
    530505    public $iCSIMdisplay=false,$iHasStroked = false;
     
    536511    public $bkg_gradtype=-1,$bkg_gradstyle=BGRAD_MARGIN;
    537512    public $bkg_gradfrom='navy', $bkg_gradto='silver';
    538     public $plot_gradtype=-1,$plot_gradstyle=BGRAD_MARGIN;
    539     public $plot_gradfrom='silver', $plot_gradto='navy';
    540 
    541513    public $titlebackground = false;
    542514    public $titlebackground_color = 'lightblue',
    543            $titlebackground_style = 1,
    544            $titlebackground_framecolor,
    545            $titlebackground_framestyle,
    546            $titlebackground_frameweight,
    547            $titlebackground_bevelheight;
     515        $titlebackground_style = 1,
     516        $titlebackground_framecolor = 'blue',
     517        $titlebackground_framestyle = 2,
     518        $titlebackground_frameweight = 1,
     519        $titlebackground_bevelheight = 3 ;
    548520    public $titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID;
    549521    public $titlebkg_scolor1='black',$titlebkg_scolor2='white';
    550     public $framebevel, $framebeveldepth;
    551     public $framebevelborder, $framebevelbordercolor;
    552     public $framebevelcolor1, $framebevelcolor2;
     522    public $framebevel = false, $framebeveldepth = 2 ;
     523    public $framebevelborder = false, $framebevelbordercolor='black';
     524    public $framebevelcolor1='white@0.4', $framebevelcolor2='black@0.4';
    553525    public $background_image_mix=100;
    554526    public $background_cflag = '';
     
    556528    public $background_cflag_mix = 100;
    557529    public $iImgTrans=false,
    558            $iImgTransHorizon = 100,$iImgTransSkewDist=150,
    559            $iImgTransDirection = 1, $iImgTransMinSize = true,
    560            $iImgTransFillColor='white',$iImgTransHighQ=false,
    561            $iImgTransBorder=false,$iImgTransHorizonPos=0.5;
     530        $iImgTransHorizon = 100,$iImgTransSkewDist=150,
     531        $iImgTransDirection = 1, $iImgTransMinSize = true,
     532        $iImgTransFillColor='white',$iImgTransHighQ=false,
     533        $iImgTransBorder=false,$iImgTransHorizonPos=0.5;
    562534    public $legend;
    563     public $graph_theme;
    564535    protected $iYAxisDeltaPos=50;
    565536    protected $iIconDepth=DEPTH_BACK;
    566537    protected $iAxisLblBgType = 0,
    567               $iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black',
    568               $iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black';
     538        $iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black',
     539        $iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black';
    569540    protected $iTables=NULL;
    570541
    571     protected $isRunningClear = false;
    572     protected $inputValues;
    573     protected $isAfterSetScale = false;
    574 
    575     // aWIdth   Width in pixels of image
    576     // aHeight   Height in pixels of image
    577     // aCachedName Name for image file in cache directory
    578     // aTimeOut  Timeout in minutes for image in cache
    579     // aInline  If true the image is streamed back in the call to Stroke()
    580     //   If false the image is just created in the cache
    581     function __construct($aWidth=300,$aHeight=200,$aCachedName='',$aTimeout=0,$aInline=true) {
    582 
    583         if( !is_numeric($aWidth) || !is_numeric($aHeight) ) {
    584             JpGraphError::RaiseL(25008);//('Image width/height argument in Graph::Graph() must be numeric');
    585         }
    586 
    587         // Initialize frame and margin
    588         $this->InitializeFrameAndMargin();
    589 
    590         // Automatically generate the image file name based on the name of the script that
    591         // generates the graph
    592         if( $aCachedName == 'auto' ) {
    593             $aCachedName=GenImgName();
    594         }
    595 
    596         // Should the image be streamed back to the browser or only to the cache?
    597         $this->inline=$aInline;
    598 
    599         $this->img = new RotImage($aWidth,$aHeight);
    600         $this->cache  = new ImgStreamCache();
    601 
    602         // Window doesn't like '?' in the file name so replace it with an '_'
    603         $aCachedName = str_replace("?","_",$aCachedName);
    604         $this->SetupCache($aCachedName, $aTimeout);
    605 
    606         $this->title = new Text();
    607         $this->title->ParagraphAlign('center');
    608         $this->title->SetFont(FF_DEFAULT,FS_NORMAL); //FF_FONT2, FS_BOLD
    609         $this->title->SetMargin(5);
    610         $this->title->SetAlign('center');
    611 
    612         $this->subtitle = new Text();
    613         $this->subtitle->ParagraphAlign('center');
    614         $this->subtitle->SetMargin(3);
    615         $this->subtitle->SetAlign('center');
    616 
    617         $this->subsubtitle = new Text();
    618         $this->subsubtitle->ParagraphAlign('center');
    619         $this->subsubtitle->SetMargin(3);
    620         $this->subsubtitle->SetAlign('center');
    621 
    622         $this->legend = new Legend();
    623         $this->footer = new Footer();
    624 
    625         // If the cached version exist just read it directly from the
    626         // cache, stream it back to browser and exit
    627         if( $aCachedName!='' && READ_CACHE && $aInline ) {
    628             if( $this->cache->GetAndStream($this->img,$aCachedName) ) {
    629                 exit();
    630             }
    631         }
    632 
    633         $this->SetTickDensity(); // Normal density
    634 
    635         $this->tabtitle = new GraphTabTitle();
    636 
    637         if (!$this->isRunningClear) {
    638             $this->inputValues = array();
    639             $this->inputValues['aWidth'] = $aWidth;
    640             $this->inputValues['aHeight'] = $aHeight;
    641             $this->inputValues['aCachedName'] = $aCachedName;
    642             $this->inputValues['aTimeout'] = $aTimeout;
    643             $this->inputValues['aInline'] = $aInline;
    644 
    645             $theme_class = DEFAULT_THEME_CLASS;
    646             if (class_exists($theme_class)) {
    647                 $this->graph_theme = new $theme_class();
    648             }
    649         }
    650     }
    651 
    652     function InitializeFrameAndMargin() {
    653         $this->doframe=true;
    654         $this->frame_color='black';
    655         $this->frame_weight=1;
    656 
    657         $this->titlebackground_framecolor = 'blue';
    658         $this->titlebackground_framestyle = 2;
    659         $this->titlebackground_frameweight = 1;
    660         $this->titlebackground_bevelheight = 3;
    661         $this->titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID;
    662         $this->titlebkg_scolor1='black';
    663         $this->titlebkg_scolor2='white';
    664         $this->framebevel = false;
    665         $this->framebeveldepth = 2;
    666         $this->framebevelborder = false;
    667         $this->framebevelbordercolor='black';
    668         $this->framebevelcolor1='white@0.4';
    669         $this->framebevelcolor2='black@0.4';
    670 
    671         $this->margin_color = array(250,250,250);
    672     }
    673 
    674     function SetupCache($aFilename,$aTimeout=60) {
    675         $this->cache_name = $aFilename;
    676         $this->cache->SetTimeOut($aTimeout);
    677     }
    678 
     542//---------------
     543// CONSTRUCTOR
     544
     545    // aWIdth           Width in pixels of image
     546    // aHeight          Height in pixels of image
     547    // aCachedName      Name for image file in cache directory
     548    // aTimeOut         Timeout in minutes for image in cache
     549    // aInline          If true the image is streamed back in the call to Stroke()
     550    //                  If false the image is just created in the cache
     551    function Graph($aWidth=300,$aHeight=200,$aCachedName="",$aTimeOut=0,$aInline=true) {
     552        GLOBAL $gJpgBrandTiming;
     553        // If timing is used create a new timing object
     554        if( $gJpgBrandTiming ) {
     555            global $tim;
     556            $tim = new JpgTimer();
     557            $tim->Push();
     558        }
     559
     560        if( !is_numeric($aWidth) || !is_numeric($aHeight) ) {
     561            JpGraphError::RaiseL(25008);//('Image width/height argument in Graph::Graph() must be numeric');
     562        }               
     563
     564        // Automatically generate the image file name based on the name of the script that
     565        // generates the graph
     566        if( $aCachedName=="auto" )
     567            $aCachedName=GenImgName();
     568                       
     569        // Should the image be streamed back to the browser or only to the cache?
     570        $this->inline=$aInline;
     571               
     572        $this->img      = new RotImage($aWidth,$aHeight);
     573
     574        $this->cache    = new ImgStreamCache($this->img);
     575        $this->cache->SetTimeOut($aTimeOut);
     576
     577        $this->title = new Text();
     578        $this->title->ParagraphAlign('center');
     579        $this->title->SetFont(FF_FONT2,FS_BOLD);
     580        $this->title->SetMargin(3);
     581        $this->title->SetAlign('center');
     582
     583        $this->subtitle = new Text();
     584        $this->subtitle->ParagraphAlign('center');
     585        $this->subtitle->SetMargin(2);
     586        $this->subtitle->SetAlign('center');
     587
     588        $this->subsubtitle = new Text();
     589        $this->subsubtitle->ParagraphAlign('center');
     590        $this->subsubtitle->SetMargin(2);
     591        $this->subsubtitle->SetAlign('center');
     592
     593        $this->legend = new Legend();
     594        $this->footer = new Footer();
     595
     596        // Window doesn't like '?' in the file name so replace it with an '_'
     597        $aCachedName = str_replace("?","_",$aCachedName);
     598
     599        // If the cached version exist just read it directly from the
     600        // cache, stream it back to browser and exit
     601        if( $aCachedName!="" && READ_CACHE && $aInline )
     602            if( $this->cache->GetAndStream($aCachedName) ) {
     603                exit();
     604            }
     605                               
     606        $this->cache_name = $aCachedName;
     607        $this->SetTickDensity(); // Normal density
     608
     609        $this->tabtitle = new GraphTabTitle();
     610    }
     611//---------------
     612// PUBLIC METHODS       
     613   
    679614    // Enable final image perspective transformation
    680615    function Set3DPerspective($aDir=1,$aHorizon=100,$aSkewDist=120,$aQuality=false,$aFillColor='#FFFFFF',$aBorder=false,$aMinSize=true,$aHorizonPos=0.5) {
    681         $this->iImgTrans = true;
    682         $this->iImgTransHorizon = $aHorizon;
    683         $this->iImgTransSkewDist= $aSkewDist;
    684         $this->iImgTransDirection = $aDir;
    685         $this->iImgTransMinSize = $aMinSize;
    686         $this->iImgTransFillColor=$aFillColor;
    687         $this->iImgTransHighQ=$aQuality;
    688         $this->iImgTransBorder=$aBorder;
    689         $this->iImgTransHorizonPos=$aHorizonPos;
     616        $this->iImgTrans = true;
     617        $this->iImgTransHorizon = $aHorizon;
     618        $this->iImgTransSkewDist= $aSkewDist;
     619        $this->iImgTransDirection = $aDir;
     620        $this->iImgTransMinSize = $aMinSize;
     621        $this->iImgTransFillColor=$aFillColor;
     622        $this->iImgTransHighQ=$aQuality;
     623        $this->iImgTransBorder=$aBorder;
     624        $this->iImgTransHorizonPos=$aHorizonPos;
    690625    }
    691626
    692627    function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    693         $this->img->ttf->SetUserFont($aNormal,$aBold,$aItalic,$aBoldIt);
     628        $this->img->ttf->SetUserFont($aNormal,$aBold,$aItalic,$aBoldIt);
    694629    }
    695630
    696631    function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    697         $this->img->ttf->SetUserFont1($aNormal,$aBold,$aItalic,$aBoldIt);
     632        $this->img->ttf->SetUserFont1($aNormal,$aBold,$aItalic,$aBoldIt);
    698633    }
    699634
    700635    function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    701         $this->img->ttf->SetUserFont2($aNormal,$aBold,$aItalic,$aBoldIt);
     636        $this->img->ttf->SetUserFont2($aNormal,$aBold,$aItalic,$aBoldIt);
    702637    }
    703638
    704639    function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    705         $this->img->ttf->SetUserFont3($aNormal,$aBold,$aItalic,$aBoldIt);
     640        $this->img->ttf->SetUserFont3($aNormal,$aBold,$aItalic,$aBoldIt);
    706641    }
    707642
    708643    // Set Image format and optional quality
    709644    function SetImgFormat($aFormat,$aQuality=75) {
    710         $this->img->SetImgFormat($aFormat,$aQuality);
     645        $this->img->SetImgFormat($aFormat,$aQuality);
    711646    }
    712647
    713648    // Should the grid be in front or back of the plot?
    714649    function SetGridDepth($aDepth) {
    715         $this->grid_depth=$aDepth;
     650        $this->grid_depth=$aDepth;
    716651    }
    717652
    718653    function SetIconDepth($aDepth) {
    719         $this->iIconDepth=$aDepth;
    720     }
    721 
     654        $this->iIconDepth=$aDepth;
     655    }
     656       
    722657    // Specify graph angle 0-360 degrees.
    723658    function SetAngle($aAngle) {
    724         $this->img->SetAngle($aAngle);
     659        $this->img->SetAngle($aAngle);
    725660    }
    726661
    727662    function SetAlphaBlending($aFlg=true) {
    728         $this->img->SetAlphaBlending($aFlg);
     663        $this->img->SetAlphaBlending($aFlg);
    729664    }
    730665
    731666    // Shortcut to image margin
    732667    function SetMargin($lm,$rm,$tm,$bm) {
    733         $this->img->SetMargin($lm,$rm,$tm,$bm);
     668        $this->img->SetMargin($lm,$rm,$tm,$bm);
    734669    }
    735670
    736671    function SetY2OrderBack($aBack=true) {
    737         $this->y2orderback = $aBack;
    738     }
    739 
    740     // Rotate the graph 90 degrees and set the margin
     672        $this->y2orderback = $aBack;
     673    }
     674
     675    // Rotate the graph 90 degrees and set the margin 
    741676    // when we have done a 90 degree rotation
    742677    function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) {
    743         $adj = ($this->img->height - $this->img->width)/2;
    744         $this->img->SetMargin($tm-$adj,$bm-$adj,$rm+$adj,$lm+$adj);
    745         $this->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2));
    746         $this->SetAngle(90);
    747         if( empty($this->yaxis) || empty($this->xaxis) ) {
    748             JpgraphError::RaiseL(25009);//('You must specify what scale to use with a call to Graph::SetScale()');
    749         }
    750         $this->xaxis->SetLabelAlign('right','center');
    751         $this->yaxis->SetLabelAlign('center','bottom');
    752     }
    753 
     678        $lm = $lm ==0 ? floor(0.2 * $this->img->width)  : $lm ;
     679        $rm = $rm ==0 ? floor(0.1 * $this->img->width)  : $rm ;
     680        $tm = $tm ==0 ? floor(0.2 * $this->img->height) : $tm ;
     681        $bm = $bm ==0 ? floor(0.1 * $this->img->height) : $bm ;
     682
     683        $adj = ($this->img->height - $this->img->width)/2;
     684        $this->img->SetMargin($tm-$adj,$bm-$adj,$rm+$adj,$lm+$adj);
     685        $this->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2));
     686        $this->SetAngle(90);
     687        if( empty($this->yaxis) || empty($this->xaxis) ) {
     688            JpgraphError::RaiseL(25009);//('You must specify what scale to use with a call to Graph::SetScale()');
     689        }
     690        $this->xaxis->SetLabelAlign('right','center');
     691        $this->yaxis->SetLabelAlign('center','bottom');
     692    }
     693       
    754694    function SetClipping($aFlg=true) {
    755         $this->iDoClipping = $aFlg ;
     695        $this->iDoClipping = $aFlg ;
    756696    }
    757697
    758698    // Add a plot object to the graph
    759699    function Add($aPlot) {
    760         if( $aPlot == null ) {
    761             JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph.");
    762         }
    763         if( is_array($aPlot) && count($aPlot) > 0 ) {
    764             $cl = $aPlot[0];
    765         }
    766         else {
    767             $cl = $aPlot;
    768         }
    769 
    770         if( $cl instanceof Text ) $this->AddText($aPlot);
    771         elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) )  $this->AddLine($aPlot);
    772         elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) $this->AddBand($aPlot);
    773         elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot);
    774         elseif( class_exists('GTextTable',false) && ($cl instanceof GTextTable) ) $this->AddTable($aPlot);
    775         else {
    776             if( is_array($aPlot) ) {
    777                 $this->plots = array_merge($this->plots,$aPlot);
    778             }
    779             else {
    780                 $this->plots[] = $aPlot;
    781             }
    782         }
    783 
    784         if ($this->graph_theme) {
    785             $this->graph_theme->SetupPlot($aPlot);
    786         }
     700        if( $aPlot == null )
     701            JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph.");
     702        if( is_array($aPlot) && count($aPlot) > 0 )
     703            $cl = $aPlot[0];
     704        else
     705            $cl = $aPlot;
     706
     707        if( $cl instanceof Text )
     708            $this->AddText($aPlot);
     709        elseif( $cl instanceof PlotLine )
     710            $this->AddLine($aPlot);
     711        elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) )
     712            $this->AddBand($aPlot);
     713        elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) )
     714            $this->AddIcon($aPlot);
     715        elseif( class_exists('GTextTable',false) && ($cl instanceof GTextTable) )
     716            $this->AddTable($aPlot);
     717        else
     718            $this->plots[] = $aPlot;
    787719    }
    788720
    789721    function AddTable($aTable) {
    790         if( is_array($aTable) ) {
    791             for($i=0; $i < count($aTable); ++$i ) {
    792                 $this->iTables[]=$aTable[$i];
    793             }
    794         }
    795         else {
    796             $this->iTables[] = $aTable ;
    797         }
     722        if( is_array($aTable) ) {
     723            for($i=0; $i < count($aTable); ++$i )
     724                $this->iTables[]=$aTable[$i];
     725        }
     726        else {
     727            $this->iTables[] = $aTable ;
     728        }       
    798729    }
    799730
    800731    function AddIcon($aIcon) {
    801         if( is_array($aIcon) ) {
    802             for($i=0; $i < count($aIcon); ++$i ) {
    803                 $this->iIcons[]=$aIcon[$i];
    804             }
    805         }
    806         else {
    807             $this->iIcons[] = $aIcon ;
    808         }
     732        if( is_array($aIcon) ) {
     733            for($i=0; $i < count($aIcon); ++$i )
     734                $this->iIcons[]=$aIcon[$i];
     735        }
     736        else {
     737            $this->iIcons[] = $aIcon ;
     738        }       
    809739    }
    810740
    811741    // Add plot to second Y-scale
    812742    function AddY2($aPlot) {
    813         if( $aPlot == null ) {
    814             JpGraphError::RaiseL(25011);//("Graph::AddY2() You tried to add a null plot to the graph.");
    815         }
    816 
    817         if( is_array($aPlot) && count($aPlot) > 0 ) {
    818             $cl = $aPlot[0];
    819         }
    820         else {
    821             $cl = $aPlot;
    822         }
    823 
    824         if( $cl instanceof Text ) {
    825             $this->AddText($aPlot,true);
    826         }
    827         elseif( class_exists('PlotLine',false) && ($cl instanceof PlotLine) ) {
    828             $this->AddLine($aPlot,true);
    829         }
    830         elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) ) {
    831             $this->AddBand($aPlot,true);
    832         }
    833         else {
    834             $this->y2plots[] = $aPlot;
    835         }
    836 
    837         if ($this->graph_theme) {
    838             $this->graph_theme->SetupPlot($aPlot);
    839         }
    840     }
    841 
     743        if( $aPlot == null )
     744            JpGraphError::RaiseL(25011);//("Graph::AddY2() You tried to add a null plot to the graph.");       
     745
     746        if( is_array($aPlot) && count($aPlot) > 0 )
     747            $cl = $aPlot[0];
     748        else
     749            $cl = $aPlot;
     750
     751        if( $cl instanceof Text )
     752            $this->AddText($aPlot,true);
     753        elseif( $cl instanceof PlotLine )
     754            $this->AddLine($aPlot,true);
     755        elseif( class_exists('PlotBand',false) && ($cl instanceof PlotBand) )
     756            $this->AddBand($aPlot,true);
     757        else
     758            $this->y2plots[] = $aPlot;
     759    }
     760       
    842761    // Add plot to the extra Y-axises
    843762    function AddY($aN,$aPlot) {
    844763
    845         if( $aPlot == null ) {
    846             JpGraphError::RaiseL(25012);//("Graph::AddYN() You tried to add a null plot to the graph.");
    847         }
    848 
    849         if( is_array($aPlot) && count($aPlot) > 0 ) {
    850             $cl = $aPlot[0];
    851         }
    852         else {
    853             $cl = $aPlot;
    854         }
    855 
    856         if( ($cl instanceof Text) ||
    857             (class_exists('PlotLine',false) && ($cl instanceof PlotLine)) ||
    858             (class_exists('PlotBand',false) && ($cl instanceof PlotBand)) ) {
    859             JpGraph::RaiseL(25013);//('You can only add standard plots to multiple Y-axis');
    860         }
    861         else {
    862             $this->ynplots[$aN][] = $aPlot;
    863         }
    864 
    865         if ($this->graph_theme) {
    866             $this->graph_theme->SetupPlot($aPlot);
    867         }
     764        if( $aPlot == null )
     765            JpGraphError::RaiseL(25012);//("Graph::AddYN() You tried to add a null plot to the graph.");       
     766
     767        if( is_array($aPlot) && count($aPlot) > 0 )
     768            $cl = $aPlot[0];
     769        else
     770            $cl = $aPlot;
     771
     772        if( ($cl instanceof Text) || ($cl instanceof PlotLine) ||
     773            (class_exists('PlotBand',false) && ($cl instanceof PlotBand)) )
     774            JpGraph::RaiseL(25013);//('You can only add standard plots to multiple Y-axis');
     775        else
     776            $this->ynplots[$aN][] = $aPlot;
    868777    }
    869778
    870779    // Add text object to the graph
    871780    function AddText($aTxt,$aToY2=false) {
    872         if( $aTxt == null ) {
    873             JpGraphError::RaiseL(25014);//("Graph::AddText() You tried to add a null text to the graph.");
    874         }
    875         if( $aToY2 ) {
    876             if( is_array($aTxt) ) {
    877                 for($i=0; $i < count($aTxt); ++$i ) {
    878                     $this->y2texts[]=$aTxt[$i];
    879                 }
    880             }
    881             else {
    882                 $this->y2texts[] = $aTxt;
    883             }
    884         }
    885         else {
    886             if( is_array($aTxt) ) {
    887                 for($i=0; $i < count($aTxt); ++$i ) {
    888                     $this->texts[]=$aTxt[$i];
    889                 }
    890             }
    891             else {
    892                 $this->texts[] = $aTxt;
    893             }
    894         }
    895     }
    896 
     781        if( $aTxt == null )
     782            JpGraphError::RaiseL(25014);//("Graph::AddText() You tried to add a null text to the graph.");             
     783        if( $aToY2 ) {
     784            if( is_array($aTxt) ) {
     785                for($i=0; $i < count($aTxt); ++$i )
     786                    $this->y2texts[]=$aTxt[$i];
     787            }
     788            else
     789                $this->y2texts[] = $aTxt;
     790        }
     791        else {
     792            if( is_array($aTxt) ) {
     793                for($i=0; $i < count($aTxt); ++$i )
     794                    $this->texts[]=$aTxt[$i];
     795            }
     796            else
     797                $this->texts[] = $aTxt;
     798        }
     799    }
     800       
    897801    // Add a line object (class PlotLine) to the graph
    898802    function AddLine($aLine,$aToY2=false) {
    899         if( $aLine == null ) {
    900             JpGraphError::RaiseL(25015);//("Graph::AddLine() You tried to add a null line to the graph.");
    901         }
    902 
    903         if( $aToY2 ) {
    904             if( is_array($aLine) ) {
    905                 for($i=0; $i < count($aLine); ++$i ) {
    906                     //$this->y2lines[]=$aLine[$i];
    907                     $this->y2plots[]=$aLine[$i];
    908                 }
    909             }
    910             else {
    911                 //$this->y2lines[] = $aLine;
    912                 $this->y2plots[]=$aLine;
    913             }
    914         }
    915         else {
    916             if( is_array($aLine) ) {
    917                 for($i=0; $i<count($aLine); ++$i ) {
    918                     //$this->lines[]=$aLine[$i];
    919                     $this->plots[]=$aLine[$i];
    920                 }
    921             }
    922             else {
    923                 //$this->lines[] = $aLine;
    924                 $this->plots[] = $aLine;
    925             }
    926         }
     803        if( $aLine == null )
     804            JpGraphError::RaiseL(25015);//("Graph::AddLine() You tried to add a null line to the graph.");     
     805
     806        if( $aToY2 ) {
     807            if( is_array($aLine) ) {
     808                for($i=0; $i < count($aLine); ++$i )
     809                    $this->y2lines[]=$aLine[$i];
     810            }
     811            else
     812                $this->y2lines[] = $aLine;
     813        }
     814        else {
     815            if( is_array($aLine) ) {
     816                for($i=0; $i<count($aLine); ++$i )
     817                    $this->lines[]=$aLine[$i];
     818            }
     819            else
     820                $this->lines[] = $aLine;
     821        }
    927822    }
    928823
    929824    // Add vertical or horizontal band
    930825    function AddBand($aBand,$aToY2=false) {
    931         if( $aBand == null ) {
    932             JpGraphError::RaiseL(25016);//(" Graph::AddBand() You tried to add a null band to the graph.");
    933         }
    934 
    935         if( $aToY2 ) {
    936             if( is_array($aBand) ) {
    937                 for($i=0; $i < count($aBand); ++$i ) {
    938                     $this->y2bands[] = $aBand[$i];
    939                 }
    940             }
    941             else {
    942                 $this->y2bands[] = $aBand;
    943             }
    944         }
    945         else {
    946             if( is_array($aBand) ) {
    947                 for($i=0; $i < count($aBand); ++$i ) {
    948                     $this->bands[] = $aBand[$i];
    949                 }
    950             }
    951             else {
    952                 $this->bands[] = $aBand;
    953             }
    954         }
    955     }
    956 
    957     function SetPlotGradient($aFrom='navy',$aTo='silver',$aGradType=2) {
    958         $this->plot_gradtype=$aGradType;
    959         $this->plot_gradfrom = $aFrom;
    960         $this->plot_gradto = $aTo;
     826        if( $aBand == null )
     827            JpGraphError::RaiseL(25016);//(" Graph::AddBand() You tried to add a null band to the graph.");
     828
     829        if( $aToY2 ) {
     830            if( is_array($aBand) ) {
     831                for($i=0; $i < count($aBand); ++$i )
     832                    $this->y2bands[] = $aBand[$i];
     833            }
     834            else
     835                $this->y2bands[] = $aBand;
     836        }
     837        else {
     838            if( is_array($aBand) ) {
     839                for($i=0; $i < count($aBand); ++$i )
     840                    $this->bands[] = $aBand[$i];
     841            }
     842            else
     843                $this->bands[] = $aBand;
     844        }
    961845    }
    962846
    963847    function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2,$aStyle=BGRAD_FRAME) {
    964         $this->bkg_gradtype=$aGradType;
    965         $this->bkg_gradstyle=$aStyle;
    966         $this->bkg_gradfrom = $aFrom;
    967         $this->bkg_gradto = $aTo;
    968     }
    969 
     848        $this->bkg_gradtype=$aGradType;
     849        $this->bkg_gradstyle=$aStyle;
     850        $this->bkg_gradfrom = $aFrom;
     851        $this->bkg_gradto = $aTo;
     852    } 
     853       
    970854    // Set a country flag in the background
    971855    function SetBackgroundCFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
    972         $this->background_cflag = $aName;
    973         $this->background_cflag_type = $aBgType;
    974         $this->background_cflag_mix = $aMix;
     856        $this->background_cflag = $aName;
     857        $this->background_cflag_type = $aBgType;
     858        $this->background_cflag_mix = $aMix;
    975859    }
    976860
    977861    // Alias for the above method
    978862    function SetBackgroundCountryFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
    979         $this->background_cflag = $aName;
    980         $this->background_cflag_type = $aBgType;
    981         $this->background_cflag_mix = $aMix;
     863        $this->background_cflag = $aName;
     864        $this->background_cflag_type = $aBgType;
     865        $this->background_cflag_mix = $aMix;
    982866    }
    983867
    984868
    985869    // Specify a background image
    986     function SetBackgroundImage($aFileName,$aBgType=BGIMG_FILLPLOT,$aImgFormat='auto') {
    987 
    988         // Get extension to determine image type
    989         if( $aImgFormat == 'auto' ) {
    990             $e = explode('.',$aFileName);
    991             if( !$e ) {
    992                 JpGraphError::RaiseL(25018,$aFileName);//('Incorrect file name for Graph::SetBackgroundImage() : '.$aFileName.' Must have a valid image extension (jpg,gif,png) when using autodetection of image type');
    993             }
    994 
    995             $valid_formats = array('png', 'jpg', 'gif');
    996             $aImgFormat = strtolower($e[count($e)-1]);
    997             if ($aImgFormat == 'jpeg')  {
    998                 $aImgFormat = 'jpg';
    999             }
    1000             elseif (!in_array($aImgFormat, $valid_formats) )  {
    1001                 JpGraphError::RaiseL(25019,$aImgFormat);//('Unknown file extension ($aImgFormat) in Graph::SetBackgroundImage() for filename: '.$aFileName);
    1002             }
    1003         }
    1004 
    1005         $this->background_image = $aFileName;
    1006         $this->background_image_type=$aBgType;
    1007         $this->background_image_format=$aImgFormat;
     870    function SetBackgroundImage($aFileName,$aBgType=BGIMG_FILLPLOT,$aImgFormat="auto") {
     871
     872        if( !USE_TRUECOLOR ) {
     873            JpGraphError::RaiseL(25017);//("You are using GD 2.x and are trying to use a background images on a non truecolor image. To use background images with GD 2.x you <b>must</b> enable truecolor by setting the USE_TRUECOLOR constant to TRUE. Due to a bug in GD 2.0.1 using any truetype fonts with truecolor images will result in very poor quality fonts.");
     874        }
     875
     876        // Get extension to determine image type
     877        if( $aImgFormat == "auto" ) {
     878            $e = explode('.',$aFileName);
     879            if( !$e ) {
     880                JpGraphError::RaiseL(25018,$aFileName);//('Incorrect file name for Graph::SetBackgroundImage() : '.$aFileName.' Must have a valid image extension (jpg,gif,png) when using autodetection of image type');
     881            }
     882
     883            $valid_formats = array('png', 'jpg', 'gif');
     884            $aImgFormat = strtolower($e[count($e)-1]);
     885            if ($aImgFormat == 'jpeg')  {
     886                $aImgFormat = 'jpg';
     887            }
     888            elseif (!in_array($aImgFormat, $valid_formats) )  {
     889                JpGraphError::RaiseL(25019,$aImgFormat);//('Unknown file extension ($aImgFormat) in Graph::SetBackgroundImage() for filename: '.$aFileName);
     890            }   
     891        }
     892
     893        $this->background_image = $aFileName;
     894        $this->background_image_type=$aBgType;
     895        $this->background_image_format=$aImgFormat;
    1008896    }
    1009897
    1010898    function SetBackgroundImageMix($aMix) {
    1011         $this->background_image_mix = $aMix ;
    1012     }
    1013 
     899        $this->background_image_mix = $aMix ;
     900    }
     901       
    1014902    // Adjust background image position
    1015903    function SetBackgroundImagePos($aXpos,$aYpos) {
    1016         $this->background_image_xpos = $aXpos ;
    1017         $this->background_image_ypos = $aYpos ;
    1018     }
    1019 
     904        $this->background_image_xpos = $aXpos ;
     905        $this->background_image_ypos = $aYpos ;
     906    }
     907       
    1020908    // Specify axis style (boxed or single)
    1021909    function SetAxisStyle($aStyle) {
    1022910        $this->iAxisStyle = $aStyle ;
    1023911    }
    1024 
     912       
    1025913    // Set a frame around the plot area
    1026914    function SetBox($aDrawPlotFrame=true,$aPlotFrameColor=array(0,0,0),$aPlotFrameWeight=1) {
    1027         $this->boxed = $aDrawPlotFrame;
    1028         $this->box_weight = $aPlotFrameWeight;
    1029         $this->box_color = $aPlotFrameColor;
    1030     }
    1031 
     915        $this->boxed = $aDrawPlotFrame;
     916        $this->box_weight = $aPlotFrameWeight;
     917        $this->box_color = $aPlotFrameColor;
     918    }
     919       
    1032920    // Specify color for the plotarea (not the margins)
    1033921    function SetColor($aColor) {
    1034         $this->plotarea_color=$aColor;
    1035     }
    1036 
     922        $this->plotarea_color=$aColor;
     923    }
     924       
    1037925    // Specify color for the margins (all areas outside the plotarea)
    1038926    function SetMarginColor($aColor) {
    1039         $this->margin_color=$aColor;
    1040     }
    1041 
     927        $this->margin_color=$aColor;
     928    }
     929       
    1042930    // Set a frame around the entire image
    1043931    function SetFrame($aDrawImgFrame=true,$aImgFrameColor=array(0,0,0),$aImgFrameWeight=1) {
    1044         $this->doframe = $aDrawImgFrame;
    1045         $this->frame_color = $aImgFrameColor;
    1046         $this->frame_weight = $aImgFrameWeight;
     932        $this->doframe = $aDrawImgFrame;
     933        $this->frame_color = $aImgFrameColor;
     934        $this->frame_weight = $aImgFrameWeight;
    1047935    }
    1048936
    1049937    function SetFrameBevel($aDepth=3,$aBorder=false,$aBorderColor='black',$aColor1='white@0.4',$aColor2='darkgray@0.4',$aFlg=true) {
    1050         $this->framebevel = $aFlg ;
    1051         $this->framebeveldepth = $aDepth ;
    1052         $this->framebevelborder = $aBorder ;
    1053         $this->framebevelbordercolor = $aBorderColor ;
    1054         $this->framebevelcolor1 = $aColor1 ;
    1055         $this->framebevelcolor2 = $aColor2 ;
    1056 
    1057         $this->doshadow = false ;
     938        $this->framebevel = $aFlg ;
     939        $this->framebeveldepth = $aDepth ;
     940        $this->framebevelborder = $aBorder ;
     941        $this->framebevelbordercolor = $aBorderColor ;
     942        $this->framebevelcolor1 = $aColor1 ;
     943        $this->framebevelcolor2 = $aColor2 ;
     944
     945        $this->doshadow = false ;
    1058946    }
    1059947
    1060948    // Set the shadow around the whole image
    1061     function SetShadow($aShowShadow=true,$aShadowWidth=5,$aShadowColor='darkgray') {
    1062         $this->doshadow = $aShowShadow;
    1063         $this->shadow_color = $aShadowColor;
    1064         $this->shadow_width = $aShadowWidth;
    1065         $this->footer->iBottomMargin += $aShadowWidth;
    1066         $this->footer->iRightMargin += $aShadowWidth;
     949    function SetShadow($aShowShadow=true,$aShadowWidth=5,$aShadowColor=array(102,102,102)) {
     950        $this->doshadow = $aShowShadow;
     951        $this->shadow_color = $aShadowColor;
     952        $this->shadow_width = $aShadowWidth;
     953        $this->footer->iBottomMargin += $aShadowWidth;
     954        $this->footer->iRightMargin += $aShadowWidth;
    1067955    }
    1068956
     
    1070958    // you must also specify the tick distance with a call to Ticks::Set()
    1071959    function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) {
    1072         $this->axtype = $aAxisType;
    1073 
    1074         if( $aYMax < $aYMin || $aXMax < $aXMin ) {
    1075             JpGraphError::RaiseL(25020);//('Graph::SetScale(): Specified Max value must be larger than the specified Min value.');
    1076         }
    1077 
    1078         $yt=substr($aAxisType,-3,3);
    1079         if( $yt == 'lin' ) {
    1080             $this->yscale = new LinearScale($aYMin,$aYMax);
    1081         }
    1082         elseif( $yt == 'int' ) {
    1083             $this->yscale = new LinearScale($aYMin,$aYMax);
    1084             $this->yscale->SetIntScale();
    1085         }
    1086         elseif( $yt == 'log' ) {
    1087             $this->yscale = new LogScale($aYMin,$aYMax);
    1088         }
    1089         else {
    1090             JpGraphError::RaiseL(25021,$aAxisType);//("Unknown scale specification for Y-scale. ($aAxisType)");
    1091         }
    1092 
    1093         $xt=substr($aAxisType,0,3);
    1094         if( $xt == 'lin' || $xt == 'tex' ) {
    1095             $this->xscale = new LinearScale($aXMin,$aXMax,'x');
    1096             $this->xscale->textscale = ($xt == 'tex');
    1097         }
    1098         elseif( $xt == 'int' ) {
    1099             $this->xscale = new LinearScale($aXMin,$aXMax,'x');
    1100             $this->xscale->SetIntScale();
    1101         }
    1102         elseif( $xt == 'dat' ) {
    1103             $this->xscale = new DateScale($aXMin,$aXMax,'x');
    1104         }
    1105         elseif( $xt == 'log' ) {
    1106             $this->xscale = new LogScale($aXMin,$aXMax,'x');
    1107         }
    1108         else {
    1109             JpGraphError::RaiseL(25022,$aAxisType);//(" Unknown scale specification for X-scale. ($aAxisType)");
    1110         }
    1111 
    1112         $this->xaxis = new Axis($this->img,$this->xscale);
    1113         $this->yaxis = new Axis($this->img,$this->yscale);
    1114         $this->xgrid = new Grid($this->xaxis);
    1115         $this->ygrid = new Grid($this->yaxis);
    1116         $this->ygrid->Show();
    1117 
    1118 
    1119         if (!$this->isRunningClear) {
    1120             $this->inputValues['aAxisType'] = $aAxisType;
    1121             $this->inputValues['aYMin'] = $aYMin;
    1122             $this->inputValues['aYMax'] = $aYMax;
    1123             $this->inputValues['aXMin'] = $aXMin;
    1124             $this->inputValues['aXMax'] = $aXMax;
    1125 
    1126             if ($this->graph_theme) {
    1127                 $this->graph_theme->ApplyGraph($this);
    1128             }
    1129         }
    1130 
    1131         $this->isAfterSetScale = true;
    1132     }
    1133 
     960        $this->axtype = $aAxisType;
     961
     962        if( $aYMax < $aYMin || $aXMax < $aXMin )
     963            JpGraphError::RaiseL(25020);//('Graph::SetScale(): Specified Max value must be larger than the specified Min value.');
     964
     965        $yt=substr($aAxisType,-3,3);
     966        if( $yt=="lin" )
     967            $this->yscale = new LinearScale($aYMin,$aYMax);
     968        elseif( $yt == "int" ) {
     969            $this->yscale = new LinearScale($aYMin,$aYMax);
     970            $this->yscale->SetIntScale();
     971        }
     972        elseif( $yt=="log" )
     973            $this->yscale = new LogScale($aYMin,$aYMax);
     974        else
     975            JpGraphError::RaiseL(25021,$aAxisType);//("Unknown scale specification for Y-scale. ($aAxisType)");
     976                       
     977        $xt=substr($aAxisType,0,3);
     978        if( $xt == "lin" || $xt == "tex" ) {
     979            $this->xscale = new LinearScale($aXMin,$aXMax,"x");
     980            $this->xscale->textscale = ($xt == "tex");
     981        }
     982        elseif( $xt == "int" ) {
     983            $this->xscale = new LinearScale($aXMin,$aXMax,"x");
     984            $this->xscale->SetIntScale();
     985        }
     986        elseif( $xt == "dat" ) {
     987            $this->xscale = new DateScale($aXMin,$aXMax,"x");
     988        }
     989        elseif( $xt == "log" )
     990            $this->xscale = new LogScale($aXMin,$aXMax,"x");
     991        else
     992            JpGraphError::RaiseL(25022,$aAxisType);//(" Unknown scale specification for X-scale. ($aAxisType)");
     993
     994        $this->xaxis = new Axis($this->img,$this->xscale);
     995        $this->yaxis = new Axis($this->img,$this->yscale);
     996        $this->xgrid = new Grid($this->xaxis);
     997        $this->ygrid = new Grid($this->yaxis); 
     998        $this->ygrid->Show();                   
     999    }
     1000       
    11341001    // Specify secondary Y scale
    1135     function SetY2Scale($aAxisType='lin',$aY2Min=1,$aY2Max=1) {
    1136         if( $aAxisType == 'lin' ) {
    1137             $this->y2scale = new LinearScale($aY2Min,$aY2Max);
    1138         }
    1139         elseif( $aAxisType == 'int' ) {
    1140             $this->y2scale = new LinearScale($aY2Min,$aY2Max);
    1141             $this->y2scale->SetIntScale();
    1142         }
    1143         elseif( $aAxisType == 'log' ) {
    1144             $this->y2scale = new LogScale($aY2Min,$aY2Max);
    1145         }
    1146         else {
    1147             JpGraphError::RaiseL(25023,$aAxisType);//("JpGraph: Unsupported Y2 axis type: $aAxisType\nMust be one of (lin,log,int)");
    1148         }
    1149 
    1150         $this->y2axis = new Axis($this->img,$this->y2scale);
    1151         $this->y2axis->scale->ticks->SetDirection(SIDE_LEFT);
    1152         $this->y2axis->SetLabelSide(SIDE_RIGHT);
    1153         $this->y2axis->SetPos('max');
    1154         $this->y2axis->SetTitleSide(SIDE_RIGHT);
    1155 
    1156         // Deafult position is the max x-value
    1157         $this->y2grid = new Grid($this->y2axis);
    1158 
    1159         if ($this->graph_theme) {
    1160           $this->graph_theme->ApplyGraph($this);
    1161         }
     1002    function SetY2Scale($aAxisType="lin",$aY2Min=1,$aY2Max=1) {
     1003        if( $aAxisType=="lin" )
     1004            $this->y2scale = new LinearScale($aY2Min,$aY2Max);
     1005        elseif( $aAxisType == "int" ) {
     1006            $this->y2scale = new LinearScale($aY2Min,$aY2Max);
     1007            $this->y2scale->SetIntScale();
     1008        }
     1009        elseif( $aAxisType=="log" ) {
     1010            $this->y2scale = new LogScale($aY2Min,$aY2Max);
     1011        }
     1012        else JpGraphError::RaiseL(25023,$aAxisType);//("JpGraph: Unsupported Y2 axis type: $aAxisType\nMust be one of (lin,log,int)");
     1013                       
     1014        $this->y2axis = new Axis($this->img,$this->y2scale);
     1015        $this->y2axis->scale->ticks->SetDirection(SIDE_LEFT);
     1016        $this->y2axis->SetLabelSide(SIDE_RIGHT);
     1017        $this->y2axis->SetPos('max');
     1018        $this->y2axis->SetTitleSide(SIDE_RIGHT);
     1019               
     1020        // Deafult position is the max x-value
     1021        $this->y2grid = new Grid($this->y2axis);                                                       
    11621022    }
    11631023
    11641024    // Set the delta position (in pixels) between the multiple Y-axis
    11651025    function SetYDeltaDist($aDist) {
    1166         $this->iYAxisDeltaPos = $aDist;
     1026        $this->iYAxisDeltaPos = $aDist;
    11671027    }
    11681028
     
    11701030    function SetYScale($aN,$aAxisType="lin",$aYMin=1,$aYMax=1) {
    11711031
    1172         if( $aAxisType == 'lin' ) {
    1173             $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
    1174         }
    1175         elseif( $aAxisType == 'int' ) {
    1176             $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
    1177             $this->ynscale[$aN]->SetIntScale();
    1178         }
    1179         elseif( $aAxisType == 'log' ) {
    1180             $this->ynscale[$aN] = new LogScale($aYMin,$aYMax);
    1181         }
    1182         else {
    1183             JpGraphError::RaiseL(25024,$aAxisType);//("JpGraph: Unsupported Y axis type: $aAxisType\nMust be one of (lin,log,int)");
    1184         }
    1185 
    1186         $this->ynaxis[$aN] = new Axis($this->img,$this->ynscale[$aN]);
    1187         $this->ynaxis[$aN]->scale->ticks->SetDirection(SIDE_LEFT);
    1188         $this->ynaxis[$aN]->SetLabelSide(SIDE_RIGHT);
    1189 
    1190         if ($this->graph_theme) {
    1191             $this->graph_theme->ApplyGraph($this);
    1192         }
     1032        if( $aAxisType=="lin" )
     1033            $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
     1034        elseif( $aAxisType == "int" ) {
     1035            $this->ynscale[$aN] = new LinearScale($aYMin,$aYMax);
     1036            $this->ynscale[$aN]->SetIntScale();
     1037        }
     1038        elseif( $aAxisType=="log" ) {
     1039            $this->ynscale[$aN] = new LogScale($aYMin,$aYMax);
     1040        }
     1041        else JpGraphError::RaiseL(25024,$aAxisType);//("JpGraph: Unsupported Y axis type: $aAxisType\nMust be one of (lin,log,int)");
     1042                       
     1043        $this->ynaxis[$aN] = new Axis($this->img,$this->ynscale[$aN]);
     1044        $this->ynaxis[$aN]->scale->ticks->SetDirection(SIDE_LEFT);
     1045        $this->ynaxis[$aN]->SetLabelSide(SIDE_RIGHT);
    11931046    }
    11941047
    11951048    // Specify density of ticks when autoscaling 'normal', 'dense', 'sparse', 'verysparse'
    1196     // The dividing factor have been determined heuristically according to my aesthetic
     1049    // The dividing factor have been determined heuristically according to my aesthetic 
    11971050    // sense (or lack off) y.m.m.v !
    11981051    function SetTickDensity($aYDensity=TICKD_NORMAL,$aXDensity=TICKD_NORMAL) {
    1199         $this->xtick_factor=30;
    1200         $this->ytick_factor=25;
    1201         switch( $aYDensity ) {
    1202             case TICKD_DENSE:
    1203                 $this->ytick_factor=12;
    1204                 break;
    1205             case TICKD_NORMAL:
    1206                 $this->ytick_factor=25;
    1207                 break;
    1208             case TICKD_SPARSE:
    1209                 $this->ytick_factor=40;
    1210                 break;
    1211             case TICKD_VERYSPARSE:
    1212                 $this->ytick_factor=100;
    1213                 break;
    1214             default:
    1215                 JpGraphError::RaiseL(25025,$densy);//("JpGraph: Unsupported Tick density: $densy");
    1216         }
    1217         switch( $aXDensity ) {
    1218             case TICKD_DENSE:
    1219                 $this->xtick_factor=15;
    1220                 break;
    1221             case TICKD_NORMAL:
    1222                 $this->xtick_factor=30;
    1223                 break;
    1224             case TICKD_SPARSE:
    1225                 $this->xtick_factor=45;
    1226                 break;
    1227             case TICKD_VERYSPARSE:
    1228                 $this->xtick_factor=60;
    1229                 break;
    1230             default:
    1231                 JpGraphError::RaiseL(25025,$densx);//("JpGraph: Unsupported Tick density: $densx");
    1232         }
    1233     }
    1234 
    1235 
    1236     // Get a string of all image map areas
     1052        $this->xtick_factor=30;
     1053        $this->ytick_factor=25;         
     1054        switch( $aYDensity ) {
     1055            case TICKD_DENSE:
     1056                $this->ytick_factor=12;                 
     1057                break;
     1058            case TICKD_NORMAL:
     1059                $this->ytick_factor=25;                 
     1060                break;
     1061            case TICKD_SPARSE:
     1062                $this->ytick_factor=40;                 
     1063                break;
     1064            case TICKD_VERYSPARSE:
     1065                $this->ytick_factor=100;                       
     1066                break;         
     1067            default:
     1068                JpGraphError::RaiseL(25025,$densy);//("JpGraph: Unsupported Tick density: $densy");
     1069        }
     1070        switch( $aXDensity ) {
     1071            case TICKD_DENSE:
     1072                $this->xtick_factor=15;                                                 
     1073                break;
     1074            case TICKD_NORMAL:
     1075                $this->xtick_factor=30;                 
     1076                break;
     1077            case TICKD_SPARSE:
     1078                $this->xtick_factor=45;                                 
     1079                break;
     1080            case TICKD_VERYSPARSE:
     1081                $this->xtick_factor=60;                                                         
     1082                break;         
     1083            default:
     1084                JpGraphError::RaiseL(25025,$densx);//("JpGraph: Unsupported Tick density: $densx");
     1085        }               
     1086    }
     1087       
     1088
     1089    // Get a string of all image map areas     
    12371090    function GetCSIMareas() {
    1238         if( !$this->iHasStroked ) {
    1239             $this->Stroke(_CSIM_SPECIALFILE);
    1240         }
    1241 
    1242         $csim = $this->title->GetCSIMAreas();
    1243         $csim .= $this->subtitle->GetCSIMAreas();
    1244         $csim .= $this->subsubtitle->GetCSIMAreas();
    1245         $csim .= $this->legend->GetCSIMAreas();
    1246 
    1247         if( $this->y2axis != NULL ) {
    1248             $csim .= $this->y2axis->title->GetCSIMAreas();
    1249         }
    1250 
    1251         if( $this->texts != null ) {
    1252             $n = count($this->texts);
    1253             for($i=0; $i < $n; ++$i ) {
    1254                 $csim .= $this->texts[$i]->GetCSIMAreas();
    1255             }
    1256         }
    1257 
    1258         if( $this->y2texts != null && $this->y2scale != null ) {
    1259             $n = count($this->y2texts);
    1260             for($i=0; $i < $n; ++$i ) {
    1261                 $csim .= $this->y2texts[$i]->GetCSIMAreas();
    1262             }
    1263         }
    1264 
    1265         if( $this->yaxis != null && $this->xaxis != null ) {
    1266             $csim .= $this->yaxis->title->GetCSIMAreas();
    1267             $csim .= $this->xaxis->title->GetCSIMAreas();
    1268         }
    1269 
    1270         $n = count($this->plots);
    1271         for( $i=0; $i < $n; ++$i ) {
    1272             $csim .= $this->plots[$i]->GetCSIMareas();
    1273         }
    1274 
    1275         $n = count($this->y2plots);
    1276         for( $i=0; $i < $n; ++$i ) {
    1277             $csim .= $this->y2plots[$i]->GetCSIMareas();
    1278         }
    1279 
    1280         $n = count($this->ynaxis);
    1281         for( $i=0; $i < $n; ++$i ) {
    1282             $m = count($this->ynplots[$i]);
    1283             for($j=0; $j < $m; ++$j ) {
    1284                 $csim .= $this->ynplots[$i][$j]->GetCSIMareas();
    1285             }
    1286         }
    1287 
    1288         if($this->iTables != null) {
    1289             $n = count($this->iTables);
    1290             for ($i = 0; $i < $n; ++$i) {
    1291                 $csim .= $this->iTables[$i]->GetCSIMareas();
    1292             }
    1293         }
    1294 
    1295         return $csim;
    1296     }
    1297 
     1091        if( !$this->iHasStroked )
     1092            $this->Stroke(_CSIM_SPECIALFILE);
     1093
     1094        $csim = $this->title->GetCSIMAreas();
     1095        $csim .= $this->subtitle->GetCSIMAreas();
     1096        $csim .= $this->subsubtitle->GetCSIMAreas();
     1097        $csim .= $this->legend->GetCSIMAreas();
     1098
     1099        if( $this->y2axis != NULL ) {
     1100            $csim .= $this->y2axis->title->GetCSIMAreas();
     1101        }
     1102
     1103        if( $this->texts != null ) {
     1104            $n = count($this->texts);
     1105            for($i=0; $i < $n; ++$i ) {
     1106                $csim .= $this->texts[$i]->GetCSIMAreas();
     1107            }
     1108        }
     1109
     1110        if( $this->y2texts != null && $this->y2scale != null ) {
     1111            $n = count($this->y2texts);
     1112            for($i=0; $i < $n; ++$i ) {
     1113                $csim .= $this->y2texts[$i]->GetCSIMAreas();
     1114            }
     1115        }
     1116
     1117        if( $this->yaxis != null && $this->xaxis != null ) {
     1118            $csim .= $this->yaxis->title->GetCSIMAreas();       
     1119            $csim .= $this->xaxis->title->GetCSIMAreas();
     1120        }
     1121
     1122        $n = count($this->plots);
     1123        for( $i=0; $i < $n; ++$i )
     1124            $csim .= $this->plots[$i]->GetCSIMareas();
     1125
     1126        $n = count($this->y2plots);
     1127        for( $i=0; $i < $n; ++$i )
     1128            $csim .= $this->y2plots[$i]->GetCSIMareas();
     1129
     1130        $n = count($this->ynaxis);
     1131        for( $i=0; $i < $n; ++$i ) {
     1132            $m = count($this->ynplots[$i]);
     1133            for($j=0; $j < $m; ++$j ) {
     1134                $csim .= $this->ynplots[$i][$j]->GetCSIMareas();
     1135            }
     1136        }
     1137
     1138        $n = count($this->iTables);
     1139        for( $i=0; $i < $n; ++$i ) {
     1140            $csim .= $this->iTables[$i]->GetCSIMareas();
     1141        }
     1142
     1143        return $csim;
     1144    }
     1145       
    12981146    // Get a complete <MAP>..</MAP> tag for the final image map
    12991147    function GetHTMLImageMap($aMapName) {
    1300         $im = "<map name=\"$aMapName\" id=\"$aMapName\" >\n";
    1301         $im .= $this->GetCSIMareas();
    1302         $im .= "</map>";
    1303         return $im;
     1148        $im = "<map name=\"$aMapName\" id=\"$aMapName\" >\n";
     1149        $im .= $this->GetCSIMareas();
     1150        $im .= "</map>";
     1151        return $im;
    13041152    }
    13051153
    13061154    function CheckCSIMCache($aCacheName,$aTimeOut=60) {
    1307         global $_SERVER;
    1308 
    1309         if( $aCacheName=='auto' ) {
    1310             $aCacheName=basename($_SERVER['PHP_SELF']);
    1311         }
    1312 
    1313         $urlarg = $this->GetURLArguments();
    1314         $this->csimcachename = CSIMCACHE_DIR.$aCacheName.$urlarg;
    1315         $this->csimcachetimeout = $aTimeOut;
    1316 
    1317         // First determine if we need to check for a cached version
    1318         // This differs from the standard cache in the sense that the
    1319         // image and CSIM map HTML file is written relative to the directory
    1320         // the script executes in and not the specified cache directory.
    1321         // The reason for this is that the cache directory is not necessarily
    1322         // accessible from the HTTP server.
    1323         if( $this->csimcachename != '' ) {
    1324             $dir = dirname($this->csimcachename);
    1325             $base = basename($this->csimcachename);
    1326             $base = strtok($base,'.');
    1327             $suffix = strtok('.');
    1328             $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
    1329             $baseimg = $dir.'/'.$base.'?'.$urlarg.'.'.$this->img->img_format;
    1330 
    1331             $timedout=false;
    1332             // Does it exist at all ?
    1333 
    1334             if( file_exists($basecsim) && file_exists($baseimg) ) {
    1335                 // Check that it hasn't timed out
    1336                 $diff=time()-filemtime($basecsim);
    1337                 if( $this->csimcachetimeout>0 && ($diff > $this->csimcachetimeout*60) ) {
    1338                     $timedout=true;
    1339                     @unlink($basecsim);
    1340                     @unlink($baseimg);
    1341                 }
    1342                 else {
    1343                     if ($fh = @fopen($basecsim, "r")) {
    1344                         fpassthru($fh);
    1345                         return true;
    1346                     }
    1347                     else {
    1348                         JpGraphError::RaiseL(25027,$basecsim);//(" Can't open cached CSIM \"$basecsim\" for reading.");
    1349                     }
    1350                 }
    1351             }
    1352         }
    1353         return false;
     1155        global $_SERVER;
     1156
     1157        if( $aCacheName=='auto' )
     1158            $aCacheName=basename($_SERVER['PHP_SELF']);
     1159
     1160        $urlarg = $this->GetURLArguments();
     1161        $this->csimcachename = CSIMCACHE_DIR.$aCacheName.$urlarg;
     1162        $this->csimcachetimeout = $aTimeOut;
     1163
     1164        // First determine if we need to check for a cached version
     1165        // This differs from the standard cache in the sense that the
     1166        // image and CSIM map HTML file is written relative to the directory
     1167        // the script executes in and not the specified cache directory.
     1168        // The reason for this is that the cache directory is not necessarily
     1169        // accessible from the HTTP server.
     1170        if( $this->csimcachename != '' ) {
     1171            $dir = dirname($this->csimcachename);
     1172            $base = basename($this->csimcachename);
     1173            $base = strtok($base,'.');
     1174            $suffix = strtok('.');
     1175            $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
     1176            $baseimg = $dir.'/'.$base.'?'.$urlarg.'.'.$this->img->img_format;
     1177
     1178            $timedout=false;
     1179            // Does it exist at all ?
     1180           
     1181            if( file_exists($basecsim) && file_exists($baseimg) ) {
     1182                // Check that it hasn't timed out
     1183                $diff=time()-filemtime($basecsim);
     1184                if( $this->csimcachetimeout>0 && ($diff > $this->csimcachetimeout*60) ) {
     1185                    $timedout=true;
     1186                    @unlink($basecsim);
     1187                    @unlink($baseimg);
     1188                }
     1189                else {
     1190                    if ($fh = @fopen($basecsim, "r")) {
     1191                        fpassthru($fh);
     1192                        return true;
     1193                    }
     1194                    else
     1195                        JpGraphError::RaiseL(25027,$basecsim);//(" Can't open cached CSIM \"$basecsim\" for reading.");
     1196                }
     1197            }
     1198        }
     1199        return false;
    13541200    }
    13551201
    13561202    // Build the argument string to be used with the csim images
    1357     static function GetURLArguments($aAddRecursiveBlocker=false) {
    1358 
    1359         if( $aAddRecursiveBlocker ) {
    1360             // This is a JPGRAPH internal defined that prevents
    1361             // us from recursively coming here again
    1362             $urlarg = _CSIM_DISPLAY.'=1';
    1363         }
    1364 
    1365         // Now reconstruct any user URL argument
    1366         reset($_GET);
    1367         foreach ($_GET as $key => $value) {
    1368             if( is_array($value) ) {
    1369                 foreach ( $value as $k => $v ) {
    1370                     $urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v);
    1371                 }
    1372             }
    1373             else {
    1374                 $urlarg .= '&amp;'.$key.'='.urlencode($value);
    1375             }
    1376         }
    1377 
    1378         // It's not ideal to convert POST argument to GET arguments
    1379         // but there is little else we can do. One idea for the
    1380         // future might be recreate the POST header in case.
    1381         reset($_POST);
    1382         foreach ($_POST as $key => $value) {
    1383             if( is_array($value) ) {
    1384                 foreach ( $value as $k => $v ) {
    1385                     $urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v);
    1386                 }
    1387             }
    1388             else {
    1389                 $urlarg .= '&amp;'.$key.'='.urlencode($value);
    1390             }
    1391         }
    1392 
    1393         return $urlarg;
     1203    function GetURLArguments() {
     1204               
     1205        // This is a JPGRAPH internal defined that prevents
     1206        // us from recursively coming here again
     1207        $urlarg = _CSIM_DISPLAY.'=1';
     1208
     1209        // Now reconstruct any user URL argument
     1210        reset($_GET);
     1211        while( list($key,$value) = each($_GET) ) {
     1212            if( is_array($value) ) {
     1213                foreach ( $value as $k => $v ) {
     1214                    $urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v);
     1215                }
     1216            }
     1217            else {
     1218                $urlarg .= '&amp;'.$key.'='.urlencode($value);
     1219            }
     1220        }
     1221
     1222        // It's not ideal to convert POST argument to GET arguments
     1223        // but there is little else we can do. One idea for the
     1224        // future might be recreate the POST header in case.
     1225        reset($_POST);
     1226        while( list($key,$value) = each($_POST) ) {
     1227            if( is_array($value) ) {
     1228                foreach ( $value as $k => $v ) {
     1229                    $urlarg .= '&amp;'.$key.'%5B'.$k.'%5D='.urlencode($v);
     1230                }
     1231            }
     1232            else {
     1233                $urlarg .= '&amp;'.$key.'='.urlencode($value);
     1234            }
     1235        }
     1236
     1237        return $urlarg;
    13941238    }
    13951239
    13961240    function SetCSIMImgAlt($aAlt) {
    1397         $this->iCSIMImgAlt = $aAlt;
     1241        $this->iCSIMImgAlt = $aAlt;
    13981242    }
    13991243
    14001244    function StrokeCSIM($aScriptName='auto',$aCSIMName='',$aBorder=0) {
    1401         if( $aCSIMName=='' ) {
    1402             // create a random map name
    1403             srand ((double) microtime() * 1000000);
    1404             $r = rand(0,100000);
    1405             $aCSIMName='__mapname'.$r.'__';
    1406         }
    1407 
    1408         if( $aScriptName=='auto' ) {
    1409             $aScriptName=basename($_SERVER['PHP_SELF']);
    1410         }
    1411 
    1412         $urlarg = $this->GetURLArguments(true);
    1413 
    1414         if( empty($_GET[_CSIM_DISPLAY]) ) {
    1415             // First determine if we need to check for a cached version
    1416             // This differs from the standard cache in the sense that the
    1417             // image and CSIM map HTML file is written relative to the directory
    1418             // the script executes in and not the specified cache directory.
    1419             // The reason for this is that the cache directory is not necessarily
    1420             // accessible from the HTTP server.
    1421             if( $this->csimcachename != '' ) {
    1422                 $dir = dirname($this->csimcachename);
    1423                 $base = basename($this->csimcachename);
    1424                 $base = strtok($base,'.');
    1425                 $suffix = strtok('.');
    1426                 $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
    1427                 $baseimg = $base.'?'.$urlarg.'.'.$this->img->img_format;
    1428 
    1429                 // Check that apache can write to directory specified
    1430 
    1431                 if( file_exists($dir) && !is_writeable($dir) ) {
    1432                     JpgraphError::RaiseL(25028,$dir);//('Apache/PHP does not have permission to write to the CSIM cache directory ('.$dir.'). Check permissions.');
    1433                 }
    1434 
    1435                 // Make sure directory exists
    1436                 $this->cache->MakeDirs($dir);
    1437 
    1438                 // Write the image file
    1439                 $this->Stroke(CSIMCACHE_DIR.$baseimg);
    1440 
    1441                 // Construct wrapper HTML and write to file and send it back to browser
    1442 
    1443                 // In the src URL we must replace the '?' with its encoding to prevent the arguments
    1444                 // to be converted to real arguments.
    1445                 $tmp = str_replace('?','%3f',$baseimg);
    1446                 $htmlwrap = $this->GetHTMLImageMap($aCSIMName)."\n".
    1447                             '<img src="'.CSIMCACHE_HTTP_DIR.$tmp.'" ismap="ismap" usemap="#'.$aCSIMName.' width="'.$this->img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
    1448 
    1449                 if($fh =  @fopen($basecsim,'w') ) {
    1450                     fwrite($fh,$htmlwrap);
    1451                     fclose($fh);
    1452                     echo $htmlwrap;
    1453                 }
    1454                 else {
    1455                     JpGraphError::RaiseL(25029,$basecsim);//(" Can't write CSIM \"$basecsim\" for writing. Check free space and permissions.");
    1456                 }
    1457             }
    1458             else {
    1459 
    1460                 if( $aScriptName=='' ) {
    1461                     JpGraphError::RaiseL(25030);//('Missing script name in call to StrokeCSIM(). You must specify the name of the actual image script as the first parameter to StrokeCSIM().');
    1462                 }
    1463                 echo $this->GetHTMLImageMap($aCSIMName) . $this->GetCSIMImgHTML($aCSIMName, $aScriptName, $aBorder);
    1464             }
    1465         }
    1466         else {
    1467             $this->Stroke();
    1468         }
    1469     }
    1470 
    1471     function StrokeCSIMImage() {
    1472         if( @$_GET[_CSIM_DISPLAY] == 1 ) {
    1473             $this->Stroke();
    1474         }
    1475     }
    1476 
    1477     function GetCSIMImgHTML($aCSIMName, $aScriptName='auto', $aBorder=0 ) {
    1478         if( $aScriptName=='auto' ) {
    1479             $aScriptName=basename($_SERVER['PHP_SELF']);
    1480         }
    1481         $urlarg = $this->GetURLArguments(true);
    1482         return "<img src=\"".$aScriptName.'?'.$urlarg."\" ismap=\"ismap\" usemap=\"#".$aCSIMName.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
     1245        if( $aCSIMName=='' ) {
     1246            // create a random map name
     1247            srand ((double) microtime() * 1000000);
     1248            $r = rand(0,100000);
     1249            $aCSIMName='__mapname'.$r.'__';
     1250        }
     1251
     1252        if( $aScriptName=='auto' )
     1253            $aScriptName=basename($_SERVER['PHP_SELF']);
     1254
     1255        $urlarg = $this->GetURLArguments();
     1256
     1257        if( empty($_GET[_CSIM_DISPLAY]) ) {
     1258            // First determine if we need to check for a cached version
     1259            // This differs from the standard cache in the sense that the
     1260            // image and CSIM map HTML file is written relative to the directory
     1261            // the script executes in and not the specified cache directory.
     1262            // The reason for this is that the cache directory is not necessarily
     1263            // accessible from the HTTP server.
     1264            if( $this->csimcachename != '' ) {
     1265                $dir = dirname($this->csimcachename);
     1266                $base = basename($this->csimcachename);
     1267                $base = strtok($base,'.');
     1268                $suffix = strtok('.');
     1269                $basecsim = $dir.'/'.$base.'?'.$urlarg.'_csim_.html';
     1270                $baseimg = $base.'?'.$urlarg.'.'.$this->img->img_format;
     1271
     1272                // Check that apache can write to directory specified
     1273
     1274                if( file_exists($dir) && !is_writeable($dir) ) {
     1275                    JpgraphError::RaiseL(25028,$dir);//('Apache/PHP does not have permission to write to the CSIM cache directory ('.$dir.'). Check permissions.');
     1276                }
     1277               
     1278                // Make sure directory exists
     1279                $this->cache->MakeDirs($dir);
     1280
     1281                // Write the image file
     1282                $this->Stroke(CSIMCACHE_DIR.$baseimg);
     1283
     1284                // Construct wrapper HTML and write to file and send it back to browser
     1285
     1286                // In the src URL we must replace the '?' with its encoding to prevent the arguments
     1287                // to be converted to real arguments.
     1288                $tmp = str_replace('?','%3f',$baseimg);
     1289                $htmlwrap = $this->GetHTMLImageMap($aCSIMName)."\n".
     1290                    '<img src="'.CSIMCACHE_HTTP_DIR.$tmp.'" ismap="ismap" usemap="#'.$aCSIMName.'" border="'.$aBorder.'" width="'.$this->img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
     1291
     1292                if($fh =  @fopen($basecsim,'w') ) {
     1293                    fwrite($fh,$htmlwrap);
     1294                    fclose($fh);
     1295                    echo $htmlwrap;
     1296                }
     1297                else
     1298                    JpGraphError::RaiseL(25029,$basecsim);//(" Can't write CSIM \"$basecsim\" for writing. Check free space and permissions.");
     1299            }
     1300            else {
     1301
     1302                if( $aScriptName=='' ) {
     1303                    JpGraphError::RaiseL(25030);//('Missing script name in call to StrokeCSIM(). You must specify the name of the actual image script as the first parameter to StrokeCSIM().');
     1304                }
     1305                echo $this->GetHTMLImageMap($aCSIMName);
     1306                echo "<img src=\"".$aScriptName.'?'.$urlarg."\" ismap=\"ismap\" usemap=\"#".$aCSIMName.'" border="'.$aBorder.'" width="'.$this->img->width.'" height="'.$this->img->height."\" alt=\"".$this->iCSIMImgAlt."\" />\n";
     1307            }
     1308        }
     1309        else {
     1310            $this->Stroke();
     1311        }
    14831312    }
    14841313
    14851314    function GetTextsYMinMax($aY2=false) {
    1486         if( $aY2 ) {
    1487             $txts = $this->y2texts;
    1488         }
    1489         else {
    1490             $txts = $this->texts;
    1491         }
    1492         $n = is_array($txts) ? count($txts) : 0;
    1493         $min=null;
    1494         $max=null;
    1495         for( $i=0; $i < $n; ++$i ) {
    1496             if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null  ) {
    1497                 if( $min === null  ) {
    1498                     $min = $max = $txts[$i]->iScalePosY ;
    1499                 }
    1500                 else {
    1501                     $min = min($min,$txts[$i]->iScalePosY);
    1502                     $max = max($max,$txts[$i]->iScalePosY);
    1503                 }
    1504             }
    1505         }
    1506         if( $min !== null ) {
    1507             return array($min,$max);
    1508         }
    1509         else {
    1510             return null;
    1511         }
     1315        if( $aY2 )
     1316            $txts = $this->y2texts;
     1317        else
     1318            $txts = $this->texts;
     1319        $n = count($txts);
     1320        $min=null;
     1321        $max=null;
     1322        for( $i=0; $i < $n; ++$i ) {
     1323            if( $txts[$i]->iScalePosY !== null &&
     1324                $txts[$i]->iScalePosX !== null  ) {
     1325                if( $min === null  ) {
     1326                    $min = $max = $txts[$i]->iScalePosY ;
     1327                }
     1328                else {
     1329                    $min = min($min,$txts[$i]->iScalePosY);
     1330                    $max = max($max,$txts[$i]->iScalePosY);
     1331                }
     1332            }
     1333        }
     1334        if( $min !== null ) {
     1335            return array($min,$max);
     1336        }
     1337        else
     1338            return null;
    15121339    }
    15131340
    15141341    function GetTextsXMinMax($aY2=false) {
    1515         if( $aY2 ) {
    1516             $txts = $this->y2texts;
    1517         }
    1518         else {
    1519             $txts = $this->texts;
    1520         }
    1521         $n = is_array($txts) ? count($txts) : 0;
    1522         $min=null;
    1523         $max=null;
    1524         for( $i=0; $i < $n; ++$i ) {
    1525             if( $txts[$i]->iScalePosY !== null && $txts[$i]->iScalePosX !== null  ) {
    1526                 if( $min === null  ) {
    1527                     $min = $max = $txts[$i]->iScalePosX ;
    1528                 }
    1529                 else {
    1530                     $min = min($min,$txts[$i]->iScalePosX);
    1531                     $max = max($max,$txts[$i]->iScalePosX);
    1532                 }
    1533             }
    1534         }
    1535         if( $min !== null ) {
    1536             return array($min,$max);
    1537         }
    1538         else {
    1539             return null;
    1540         }
     1342        if( $aY2 )
     1343            $txts = $this->y2texts;
     1344        else
     1345            $txts = $this->texts;
     1346        $n = count($txts);
     1347        $min=null;
     1348        $max=null;
     1349        for( $i=0; $i < $n; ++$i ) {
     1350            if( $txts[$i]->iScalePosY !== null &&
     1351                $txts[$i]->iScalePosX !== null  ) {
     1352                if( $min === null  ) {
     1353                    $min = $max = $txts[$i]->iScalePosX ;
     1354                }
     1355                else {
     1356                    $min = min($min,$txts[$i]->iScalePosX);
     1357                    $max = max($max,$txts[$i]->iScalePosX);
     1358                }
     1359            }
     1360        }
     1361        if( $min !== null ) {
     1362            return array($min,$max);
     1363        }
     1364        else
     1365            return null;
    15411366    }
    15421367
    15431368    function GetXMinMax() {
    1544 
    1545         list($min,$ymin) = $this->plots[0]->Min();
    1546         list($max,$ymax) = $this->plots[0]->Max();
    1547 
    1548         $i=0;
    1549         // Some plots, e.g. PlotLine should not affect the scale
    1550         // and will return (null,null). We should ignore those
    1551         // values.
    1552         while( ($min===null || $max === null) && ($i < count($this->plots)-1) ) {
    1553             ++$i;
    1554             list($min,$ymin) = $this->plots[$i]->Min();
    1555             list($max,$ymax) = $this->plots[$i]->Max();
    1556         }
    1557 
    1558         foreach( $this->plots as $p ) {
    1559             list($xmin,$ymin) = $p->Min();
    1560             list($xmax,$ymax) = $p->Max();
    1561 
    1562             if( $xmin !== null && $xmax !== null ) {
    1563                 $min = Min($xmin,$min);
    1564                 $max = Max($xmax,$max);
    1565             }
    1566         }
    1567 
    1568         if( $this->y2axis != null ) {
    1569             foreach( $this->y2plots as $p ) {
    1570                 list($xmin,$ymin) = $p->Min();
    1571                 list($xmax,$ymax) = $p->Max();
    1572                 if( $xmin !== null && $xmax !== null ) {
    1573                     $min = Min($xmin, $min);
    1574                     $max = Max($xmax, $max);
    1575                 }
    1576             }
    1577         }
    1578 
    1579         $n = count($this->ynaxis);
    1580         for( $i=0; $i < $n; ++$i ) {
    1581             if( $this->ynaxis[$i] != null) {
    1582                 foreach( $this->ynplots[$i] as $p ) {
    1583                     list($xmin,$ymin) = $p->Min();
    1584                     list($xmax,$ymax) = $p->Max();
    1585                     if( $xmin !== null && $xmax !== null ) {
    1586                         $min = Min($xmin, $min);
    1587                         $max = Max($xmax, $max);
    1588                     }
    1589                 }
    1590             }
    1591         }
    1592         return array($min,$max);
     1369        list($min,$ymin) = $this->plots[0]->Min();
     1370        list($max,$ymax) = $this->plots[0]->Max();
     1371        foreach( $this->plots as $p ) {
     1372            list($xmin,$ymin) = $p->Min();
     1373            list($xmax,$ymax) = $p->Max();                     
     1374            $min = Min($xmin,$min);
     1375            $max = Max($xmax,$max);
     1376        }
     1377
     1378        if( $this->y2axis != null ) {
     1379            foreach( $this->y2plots as $p ) {
     1380                list($xmin,$ymin) = $p->Min();
     1381                        list($xmax,$ymax) = $p->Max();                 
     1382                        $min = Min($xmin,$min);
     1383                        $max = Max($xmax,$max);
     1384            }               
     1385        }
     1386
     1387        $n = count($this->ynaxis);
     1388        for( $i=0; $i < $n; ++$i ) {
     1389            if( $this->ynaxis[$i] != null) {
     1390                foreach( $this->ynplots[$i] as $p ) {
     1391                    list($xmin,$ymin) = $p->Min();
     1392                    list($xmax,$ymax) = $p->Max();                     
     1393                    $min = Min($xmin,$min);
     1394                    $max = Max($xmax,$max);
     1395                }                   
     1396            }
     1397        }
     1398        return array($min,$max);
    15931399    }
    15941400
    15951401    function AdjustMarginsForTitles() {
    1596         $totrequired =
    1597             ($this->title->t != ''
    1598                 ? $this->title->GetTextHeight($this->img) + $this->title->margin + 5 * SUPERSAMPLING_SCALE
    1599                 : 0 ) +
    1600             ($this->subtitle->t != ''
    1601                 ? $this->subtitle->GetTextHeight($this->img) + $this->subtitle->margin + 5 * SUPERSAMPLING_SCALE
    1602                 : 0 ) +
    1603             ($this->subsubtitle->t != ''
    1604                 ? $this->subsubtitle->GetTextHeight($this->img) + $this->subsubtitle->margin + 5 * SUPERSAMPLING_SCALE
    1605                 : 0 ) ;
    1606 
    1607         $btotrequired = 0;
    1608         if($this->xaxis != null &&  !$this->xaxis->hide && !$this->xaxis->hide_labels ) {
    1609             // Minimum bottom margin
    1610             if( $this->xaxis->title->t != '' ) {
    1611                 if( $this->img->a == 90 ) {
    1612                     $btotrequired = $this->yaxis->title->GetTextHeight($this->img) + 7 ;
    1613                 }
    1614                 else {
    1615                     $btotrequired = $this->xaxis->title->GetTextHeight($this->img) + 7 ;
    1616                 }
    1617             }
    1618             else {
    1619                 $btotrequired = 0;
    1620             }
    1621 
    1622             if( $this->img->a == 90 ) {
    1623                 $this->img->SetFont($this->yaxis->font_family,$this->yaxis->font_style,
    1624                 $this->yaxis->font_size);
    1625                 $lh = $this->img->GetTextHeight('Mg',$this->yaxis->label_angle);
    1626             }
    1627             else {
    1628                 $this->img->SetFont($this->xaxis->font_family,$this->xaxis->font_style,
    1629                 $this->xaxis->font_size);
    1630                 $lh = $this->img->GetTextHeight('Mg',$this->xaxis->label_angle);
    1631             }
    1632 
    1633             $btotrequired += $lh + 6;
    1634         }
    1635 
    1636         if( $this->img->a == 90 ) {
    1637             // DO Nothing. It gets too messy to do this properly for 90 deg...
    1638         }
    1639         else{
    1640             // need more top margin
    1641             if( $this->img->top_margin < $totrequired ) {
    1642                 $this->SetMargin(
    1643                     $this->img->raw_left_margin,
    1644                     $this->img->raw_right_margin,
    1645                     $totrequired / SUPERSAMPLING_SCALE,
    1646                     $this->img->raw_bottom_margin
    1647                 );
    1648             }
    1649 
    1650             // need more bottom margin
    1651             if( $this->img->bottom_margin < $btotrequired ) {
    1652                 $this->SetMargin(
    1653                     $this->img->raw_left_margin,
    1654                     $this->img->raw_right_margin,
    1655                     $this->img->raw_top_margin,
    1656                     $btotrequired / SUPERSAMPLING_SCALE
    1657                 );
    1658             }
    1659         }
    1660     }
    1661 
    1662     function StrokeStore($aStrokeFileName) {
    1663         // Get the handler to prevent the library from sending the
    1664         // image to the browser
    1665         $ih = $this->Stroke(_IMG_HANDLER);
    1666 
    1667         // Stroke it to a file
    1668         $this->img->Stream($aStrokeFileName);
    1669 
    1670         // Send it back to browser
    1671         $this->img->Headers();
    1672         $this->img->Stream();
    1673     }
    1674 
    1675     function doAutoscaleXAxis() {
    1676     //Check if we should autoscale x-axis
    1677         if( !$this->xscale->IsSpecified() ) {
    1678             if( substr($this->axtype,0,4) == "text" ) {
    1679                 $max=0;
    1680                 $n = count($this->plots);
    1681                 for($i=0; $i < $n; ++$i ) {
    1682                     $p = $this->plots[$i];
    1683                     // We need some unfortunate sub class knowledge here in order
    1684                     // to increase number of data points in case it is a line plot
    1685                     // which has the barcenter set. If not it could mean that the
    1686                     // last point of the data is outside the scale since the barcenter
    1687                     // settings means that we will shift the entire plot half a tick step
    1688                     // to the right in oder to align with the center of the bars.
    1689                     if( class_exists('BarPlot',false) ) {
    1690                         $cl = strtolower(get_class($p));
    1691                         if( (class_exists('BarPlot',false) && ($p instanceof BarPlot)) || empty($p->barcenter) ) {
    1692                             $max=max($max,$p->numpoints-1);
    1693                         }
    1694                         else {
    1695                             $max=max($max,$p->numpoints);
    1696                         }
    1697                     }
    1698                     else {
    1699                         if( empty($p->barcenter) ) {
    1700                             $max=max($max,$p->numpoints-1);
    1701                         }
    1702                         else {
    1703                             $max=max($max,$p->numpoints);
    1704                         }
    1705                     }
    1706                 }
    1707                 $min=0;
    1708                 if( $this->y2axis != null ) {
    1709                     foreach( $this->y2plots as $p ) {
    1710                         $max=max($max,$p->numpoints-1);
    1711                     }
    1712                 }
    1713                 $n = count($this->ynaxis);
    1714                 for( $i=0; $i < $n; ++$i ) {
    1715                     if( $this->ynaxis[$i] != null) {
    1716                         foreach( $this->ynplots[$i] as $p ) {
    1717                             $max=max($max,$p->numpoints-1);
    1718                         }
    1719                     }
    1720                 }
    1721 
    1722                 $this->xscale->Update($this->img,$min,$max);
    1723                 $this->xscale->ticks->Set($this->xaxis->tick_step,1);
    1724                 $this->xscale->ticks->SupressMinorTickMarks();
    1725             }
    1726             else {
    1727                 list($min,$max) = $this->GetXMinMax();
    1728 
    1729                 $lres = $this->GetLinesXMinMax($this->lines);
    1730                 if( $lres ) {
    1731                     list($linmin,$linmax) = $lres ;
    1732                     $min = min($min,$linmin);
    1733                     $max = max($max,$linmax);
    1734                 }
    1735 
    1736                 $lres = $this->GetLinesXMinMax($this->y2lines);
    1737                 if( $lres ) {
    1738                     list($linmin,$linmax) = $lres ;
    1739                     $min = min($min,$linmin);
    1740                     $max = max($max,$linmax);
    1741                 }
    1742 
    1743                 $tres = $this->GetTextsXMinMax();
    1744                 if( $tres ) {
    1745                     list($tmin,$tmax) = $tres ;
    1746                     $min = min($min,$tmin);
    1747                     $max = max($max,$tmax);
    1748                 }
    1749 
    1750                 $tres = $this->GetTextsXMinMax(true);
    1751                 if( $tres ) {
    1752                     list($tmin,$tmax) = $tres ;
    1753                     $min = min($min,$tmin);
    1754                     $max = max($max,$tmax);
    1755                 }
    1756 
    1757                 $this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor));
    1758             }
    1759 
    1760             //Adjust position of y-axis and y2-axis to minimum/maximum of x-scale
    1761             if( !is_numeric($this->yaxis->pos) && !is_string($this->yaxis->pos) ) {
    1762                 $this->yaxis->SetPos($this->xscale->GetMinVal());
    1763             }
    1764         }
    1765         elseif( $this->xscale->IsSpecified() &&
    1766                 ( $this->xscale->auto_ticks || !$this->xscale->ticks->IsSpecified()) ) {
    1767             // The tick calculation will use the user suplied min/max values to determine
    1768             // the ticks. If auto_ticks is false the exact user specifed min and max
    1769             // values will be used for the scale.
    1770             // If auto_ticks is true then the scale might be slightly adjusted
    1771             // so that the min and max values falls on an even major step.
    1772             $min = $this->xscale->scale[0];
    1773             $max = $this->xscale->scale[1];
    1774             $this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor),false);
    1775 
    1776             // Now make sure we show enough precision to accurate display the
    1777             // labels. If this is not done then the user might end up with
    1778             // a scale that might actually start with, say 13.5, butdue to rounding
    1779             // the scale label will ony show 14.
    1780             if( abs(floor($min)-$min) > 0 ) {
    1781 
    1782                 // If the user has set a format then we bail out
    1783                 if( $this->xscale->ticks->label_formatstr == '' && $this->xscale->ticks->label_dateformatstr == '' ) {
    1784                     $this->xscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
    1785                 }
    1786             }
    1787         }
    1788 
    1789         // Position the optional Y2 and Yn axis to the rightmost position of the x-axis
    1790         if( $this->y2axis != null ) {
    1791             if( !is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos) ) {
    1792                 $this->y2axis->SetPos($this->xscale->GetMaxVal());
    1793             }
    1794             $this->y2axis->SetTitleSide(SIDE_RIGHT);
    1795         }
    1796 
    1797         $n = count($this->ynaxis);
    1798         $nY2adj = $this->y2axis != null ? $this->iYAxisDeltaPos : 0;
    1799         for( $i=0; $i < $n; ++$i ) {
    1800             if( $this->ynaxis[$i] != null ) {
    1801                 if( !is_numeric($this->ynaxis[$i]->pos) && !is_string($this->ynaxis[$i]->pos) ) {
    1802                     $this->ynaxis[$i]->SetPos($this->xscale->GetMaxVal());
    1803                     $this->ynaxis[$i]->SetPosAbsDelta($i*$this->iYAxisDeltaPos + $nY2adj);
    1804                 }
    1805                 $this->ynaxis[$i]->SetTitleSide(SIDE_RIGHT);
    1806             }
    1807         }
    1808     }
    1809 
    1810 
    1811     function doAutoScaleYnAxis() {
    1812 
    1813         if( $this->y2scale != null) {
    1814             if( !$this->y2scale->IsSpecified() && count($this->y2plots)>0 ) {
    1815                 list($min,$max) = $this->GetPlotsYMinMax($this->y2plots);
    1816 
    1817                 $lres = $this->GetLinesYMinMax($this->y2lines);
    1818                 if( is_array($lres) ) {
    1819                     list($linmin,$linmax) = $lres ;
    1820                     $min = min($min,$linmin);
    1821                     $max = max($max,$linmax);
    1822                 }
    1823                 $tres = $this->GetTextsYMinMax(true);
    1824                 if( is_array($tres) ) {
    1825                     list($tmin,$tmax) = $tres ;
    1826                     $min = min($min,$tmin);
    1827                     $max = max($max,$tmax);
    1828                 }
    1829                 $this->y2scale->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor);
    1830             }
    1831             elseif( $this->y2scale->IsSpecified() && ( $this->y2scale->auto_ticks || !$this->y2scale->ticks->IsSpecified()) ) {
    1832                 // The tick calculation will use the user suplied min/max values to determine
    1833                 // the ticks. If auto_ticks is false the exact user specifed min and max
    1834                 // values will be used for the scale.
    1835                 // If auto_ticks is true then the scale might be slightly adjusted
    1836                 // so that the min and max values falls on an even major step.
    1837                 $min = $this->y2scale->scale[0];
    1838                 $max = $this->y2scale->scale[1];
    1839                 $this->y2scale->AutoScale($this->img,$min,$max,
    1840                 $this->img->plotheight/$this->ytick_factor,
    1841                 $this->y2scale->auto_ticks);
    1842 
    1843                 // Now make sure we show enough precision to accurate display the
    1844                 // labels. If this is not done then the user might end up with
    1845                 // a scale that might actually start with, say 13.5, butdue to rounding
    1846                 // the scale label will ony show 14.
    1847                 if( abs(floor($min)-$min) > 0 ) {
    1848                     // If the user has set a format then we bail out
    1849                     if( $this->y2scale->ticks->label_formatstr == '' && $this->y2scale->ticks->label_dateformatstr == '' ) {
    1850                         $this->y2scale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
    1851                     }
    1852                 }
    1853 
    1854             }
    1855         }
    1856 
    1857 
    1858         //
    1859         // Autoscale the extra Y-axises
    1860         //
    1861         $n = count($this->ynaxis);
    1862         for( $i=0; $i < $n; ++$i ) {
    1863             if( $this->ynscale[$i] != null) {
    1864                 if( !$this->ynscale[$i]->IsSpecified() && count($this->ynplots[$i])>0 ) {
    1865                     list($min,$max) = $this->GetPlotsYMinMax($this->ynplots[$i]);
    1866                     $this->ynscale[$i]->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor);
    1867                 }
    1868                 elseif( $this->ynscale[$i]->IsSpecified() && ( $this->ynscale[$i]->auto_ticks || !$this->ynscale[$i]->ticks->IsSpecified()) ) {
    1869                     // The tick calculation will use the user suplied min/max values to determine
    1870                     // the ticks. If auto_ticks is false the exact user specifed min and max
    1871                     // values will be used for the scale.
    1872                     // If auto_ticks is true then the scale might be slightly adjusted
    1873                     // so that the min and max values falls on an even major step.
    1874                     $min = $this->ynscale[$i]->scale[0];
    1875                     $max = $this->ynscale[$i]->scale[1];
    1876                     $this->ynscale[$i]->AutoScale($this->img,$min,$max,
    1877                     $this->img->plotheight/$this->ytick_factor,
    1878                     $this->ynscale[$i]->auto_ticks);
    1879 
    1880                     // Now make sure we show enough precision to accurate display the
    1881                     // labels. If this is not done then the user might end up with
    1882                     // a scale that might actually start with, say 13.5, butdue to rounding
    1883                     // the scale label will ony show 14.
    1884                     if( abs(floor($min)-$min) > 0 ) {
    1885                         // If the user has set a format then we bail out
    1886                         if( $this->ynscale[$i]->ticks->label_formatstr == '' && $this->ynscale[$i]->ticks->label_dateformatstr == '' ) {
    1887                             $this->ynscale[$i]->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
    1888                         }
    1889                     }
    1890                 }
    1891             }
    1892         }
    1893     }
    1894 
    1895     function doAutoScaleYAxis() {
    1896 
    1897         //Check if we should autoscale y-axis
    1898         if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) {
    1899             list($min,$max) = $this->GetPlotsYMinMax($this->plots);
    1900             $lres = $this->GetLinesYMinMax($this->lines);
    1901             if( is_array($lres) ) {
    1902                 list($linmin,$linmax) = $lres ;
    1903                 $min = min($min,$linmin);
    1904                 $max = max($max,$linmax);
    1905             }
    1906             $tres = $this->GetTextsYMinMax();
    1907             if( is_array($tres) ) {
    1908                 list($tmin,$tmax) = $tres ;
    1909                 $min = min($min,$tmin);
    1910                 $max = max($max,$tmax);
    1911             }
    1912             $this->yscale->AutoScale($this->img,$min,$max,
    1913             $this->img->plotheight/$this->ytick_factor);
    1914         }
    1915         elseif( $this->yscale->IsSpecified() && ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) {
    1916             // The tick calculation will use the user suplied min/max values to determine
    1917             // the ticks. If auto_ticks is false the exact user specifed min and max
    1918             // values will be used for the scale.
    1919             // If auto_ticks is true then the scale might be slightly adjusted
    1920             // so that the min and max values falls on an even major step.
    1921             $min = $this->yscale->scale[0];
    1922             $max = $this->yscale->scale[1];
    1923             $this->yscale->AutoScale($this->img,$min,$max,
    1924             $this->img->plotheight/$this->ytick_factor,
    1925             $this->yscale->auto_ticks);
    1926 
    1927             // Now make sure we show enough precision to accurate display the
    1928             // labels. If this is not done then the user might end up with
    1929             // a scale that might actually start with, say 13.5, butdue to rounding
    1930             // the scale label will ony show 14.
    1931             if( abs(floor($min)-$min) > 0 ) {
    1932 
    1933                 // If the user has set a format then we bail out
    1934                 if( $this->yscale->ticks->label_formatstr == '' && $this->yscale->ticks->label_dateformatstr == '' ) {
    1935                     $this->yscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
    1936                 }
    1937             }
    1938         }
    1939 
    1940     }
    1941 
    1942     function InitScaleConstants() {
    1943         // Setup scale constants
    1944         if( $this->yscale ) $this->yscale->InitConstants($this->img);
    1945         if( $this->xscale ) $this->xscale->InitConstants($this->img);
    1946         if( $this->y2scale ) $this->y2scale->InitConstants($this->img);
    1947 
    1948         $n=count($this->ynscale);
    1949         for($i=0; $i < $n; ++$i) {
    1950             if( $this->ynscale[$i] ) {
    1951                 $this->ynscale[$i]->InitConstants($this->img);
    1952             }
    1953         }
    1954     }
    1955 
    1956     function doPrestrokeAdjustments() {
    1957 
    1958         // Do any pre-stroke adjustment that is needed by the different plot types
    1959         // (i.e bar plots want's to add an offset to the x-labels etc)
    1960         for($i=0; $i < count($this->plots) ; ++$i ) {
    1961             $this->plots[$i]->PreStrokeAdjust($this);
    1962             $this->plots[$i]->DoLegend($this);
    1963         }
    1964 
    1965         // Any plots on the second Y scale?
    1966         if( $this->y2scale != null ) {
    1967             for($i=0; $i<count($this->y2plots) ; ++$i ) {
    1968                 $this->y2plots[$i]->PreStrokeAdjust($this);
    1969                 $this->y2plots[$i]->DoLegend($this);
    1970             }
    1971         }
    1972 
    1973         // Any plots on the extra Y axises?
    1974         $n = count($this->ynaxis);
    1975         for($i=0; $i<$n ; ++$i ) {
    1976             if( $this->ynplots == null || $this->ynplots[$i] == null) {
    1977                 JpGraphError::RaiseL(25032,$i);//("No plots for Y-axis nbr:$i");
    1978             }
    1979             $m = count($this->ynplots[$i]);
    1980             for($j=0; $j < $m; ++$j ) {
    1981                 $this->ynplots[$i][$j]->PreStrokeAdjust($this);
    1982                 $this->ynplots[$i][$j]->DoLegend($this);
    1983             }
    1984         }
    1985     }
    1986 
    1987     function StrokeBands($aDepth,$aCSIM) {
    1988     // Stroke bands
    1989         if( $this->bands != null && !$aCSIM) {
    1990             for($i=0; $i < count($this->bands); ++$i) {
    1991             // Stroke all bands that asks to be in the background
    1992                 if( $this->bands[$i]->depth == $aDepth ) {
    1993                     $this->bands[$i]->Stroke($this->img,$this->xscale,$this->yscale);
    1994                 }
    1995             }
    1996         }
    1997 
    1998         if( $this->y2bands != null && $this->y2scale != null && !$aCSIM ) {
    1999             for($i=0; $i < count($this->y2bands); ++$i) {
    2000             // Stroke all bands that asks to be in the foreground
    2001                 if( $this->y2bands[$i]->depth == $aDepth ) {
    2002                     $this->y2bands[$i]->Stroke($this->img,$this->xscale,$this->y2scale);
    2003                 }
    2004             }
    2005         }
    2006     }
    2007 
     1402        $totrequired =
     1403            ($this->title->t != '' ?
     1404             $this->title->GetTextHeight($this->img) + $this->title->margin + 5 : 0 ) +
     1405            ($this->subtitle->t != '' ?
     1406             $this->subtitle->GetTextHeight($this->img) + $this->subtitle->margin + 5 : 0 ) +
     1407            ($this->subsubtitle->t != '' ?
     1408             $this->subsubtitle->GetTextHeight($this->img) + $this->subsubtitle->margin + 5 : 0 ) ;
     1409       
     1410
     1411        $btotrequired = 0;
     1412        if($this->xaxis != null &&  !$this->xaxis->hide && !$this->xaxis->hide_labels ) {
     1413            // Minimum bottom margin
     1414            if( $this->xaxis->title->t != '' ) {
     1415                if( $this->img->a == 90 )
     1416                    $btotrequired = $this->yaxis->title->GetTextHeight($this->img) + 5 ;
     1417                else
     1418                    $btotrequired = $this->xaxis->title->GetTextHeight($this->img) + 5 ;
     1419            }
     1420            else
     1421                $btotrequired = 0;
     1422           
     1423            if( $this->img->a == 90 ) {
     1424                $this->img->SetFont($this->yaxis->font_family,$this->yaxis->font_style,
     1425                                    $this->yaxis->font_size);
     1426                $lh = $this->img->GetTextHeight('Mg',$this->yaxis->label_angle);
     1427            }
     1428            else {
     1429                $this->img->SetFont($this->xaxis->font_family,$this->xaxis->font_style,
     1430                                    $this->xaxis->font_size);
     1431                $lh = $this->img->GetTextHeight('Mg',$this->xaxis->label_angle);
     1432            }
     1433           
     1434            $btotrequired += $lh + 5;
     1435        }
     1436
     1437        if( $this->img->a == 90 ) {
     1438            // DO Nothing. It gets too messy to do this properly for 90 deg...
     1439        }
     1440        else{
     1441            if( $this->img->top_margin < $totrequired ) {
     1442                $this->SetMargin($this->img->left_margin,$this->img->right_margin,
     1443                                 $totrequired,$this->img->bottom_margin);
     1444            }
     1445            if( $this->img->bottom_margin < $btotrequired ) {
     1446                $this->SetMargin($this->img->left_margin,$this->img->right_margin,
     1447                                 $this->img->top_margin,$btotrequired);
     1448            }
     1449        }
     1450    }
    20081451
    20091452    // Stroke the graph
    2010     // $aStrokeFileName If != "" the image will be written to this file and NOT
     1453    // $aStrokeFileName If != "" the image will be written to this file and NOT
    20111454    // streamed back to the browser
    2012     function Stroke($aStrokeFileName='') {
    2013         // Fist make a sanity check that user has specified a scale
    2014         if( empty($this->yscale) ) {
    2015             JpGraphError::RaiseL(25031);//('You must specify what scale to use with a call to Graph::SetScale().');
    2016         }
    2017 
    2018         // Start by adjusting the margin so that potential titles will fit.
    2019         $this->AdjustMarginsForTitles();
    2020 
    2021         // Give the plot a chance to do any scale adjuments the individual plots
    2022         // wants to do. Right now this is only used by the contour plot to set scale
    2023         // limits
    2024         for($i=0; $i < count($this->plots) ; ++$i ) {
    2025             $this->plots[$i]->PreScaleSetup($this);
    2026         }
    2027 
    2028         // Init scale constants that are used to calculate the transformation from
    2029         // world to pixel coordinates
    2030         $this->InitScaleConstants();
    2031 
    2032         // If the filename is the predefined value = '_csim_special_'
    2033         // we assume that the call to stroke only needs to do enough
    2034         // to correctly generate the CSIM maps.
    2035         // We use this variable to skip things we don't strictly need
    2036         // to do to generate the image map to improve performance
    2037         // a best we can. Therefor you will see a lot of tests !$_csim in the
    2038         // code below.
    2039         $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
    2040 
    2041         // If we are called the second time (perhaps the user has called GetHTMLImageMap()
    2042         // himself then the legends have alsready been populated once in order to get the
    2043         // CSIM coordinats. Since we do not want the legends to be populated a second time
    2044         // we clear the legends
    2045         $this->legend->Clear();
    2046 
    2047         // We need to know if we have stroked the plot in the
    2048         // GetCSIMareas. Otherwise the CSIM hasn't been generated
    2049         // and in the case of GetCSIM called before stroke to generate
    2050         // CSIM without storing an image to disk GetCSIM must call Stroke.
    2051         $this->iHasStroked = true;
    2052 
    2053         // Setup pre-stroked adjustments and Legends
    2054         $this->doPrestrokeAdjustments();
    2055 
    2056         if ($this->graph_theme) {
    2057             $this->graph_theme->PreStrokeApply($this);
    2058         }
    2059 
    2060         // Bail out if any of the Y-axis not been specified and
    2061         // has no plots. (This means it is impossible to do autoscaling and
    2062         // no other scale was given so we can't possible draw anything). If you use manual
    2063         // scaling you also have to supply the tick steps as well.
    2064         if( (!$this->yscale->IsSpecified() && count($this->plots)==0) ||
    2065             ($this->y2scale!=null && !$this->y2scale->IsSpecified() && count($this->y2plots)==0) ) {
    2066             //$e = "n=".count($this->y2plots)."\n";
    2067             // $e = "Can't draw unspecified Y-scale.<br>\nYou have either:<br>\n";
    2068             // $e .= "1. Specified an Y axis for autoscaling but have not supplied any plots<br>\n";
    2069             // $e .= "2. Specified a scale manually but have forgot to specify the tick steps";
    2070             JpGraphError::RaiseL(25026);
    2071         }
    2072 
    2073         // Bail out if no plots and no specified X-scale
    2074         if( (!$this->xscale->IsSpecified() && count($this->plots)==0 && count($this->y2plots)==0) ) {
    2075             JpGraphError::RaiseL(25034);//("<strong>JpGraph: Can't draw unspecified X-scale.</strong><br>No plots.<br>");
    2076         }
    2077 
    2078         // Autoscale the normal Y-axis
    2079         $this->doAutoScaleYAxis();
    2080 
    2081         // Autoscale all additiopnal y-axis
    2082         $this->doAutoScaleYnAxis();
    2083 
    2084         // Autoscale the regular x-axis and position the y-axis properly
    2085         $this->doAutoScaleXAxis();
    2086 
    2087         // If we have a negative values and x-axis position is at 0
    2088         // we need to supress the first and possible the last tick since
    2089         // they will be drawn on top of the y-axis (and possible y2 axis)
    2090         // The test below might seem strange the reasone being that if
    2091         // the user hasn't specified a value for position this will not
    2092         // be set until we do the stroke for the axis so as of now it
    2093         // is undefined.
    2094         // For X-text scale we ignore all this since the tick are usually
    2095         // much further in and not close to the Y-axis. Hence the test
    2096         // for 'text'
    2097         if( ($this->yaxis->pos==$this->xscale->GetMinVal() || (is_string($this->yaxis->pos) && $this->yaxis->pos=='min')) &&
    2098             !is_numeric($this->xaxis->pos) && $this->yscale->GetMinVal() < 0 &&
    2099             substr($this->axtype,0,4) != 'text' && $this->xaxis->pos != 'min' ) {
    2100 
    2101             //$this->yscale->ticks->SupressZeroLabel(false);
    2102             $this->xscale->ticks->SupressFirst();
    2103             if( $this->y2axis != null ) {
    2104                 $this->xscale->ticks->SupressLast();
    2105             }
    2106         }
    2107         elseif( !is_numeric($this->yaxis->pos) && $this->yaxis->pos=='max' ) {
    2108             $this->xscale->ticks->SupressLast();
    2109         }
    2110 
    2111         if( !$_csim ) {
    2112             $this->StrokePlotArea();
    2113             if( $this->iIconDepth == DEPTH_BACK ) {
    2114                 $this->StrokeIcons();
    2115             }
    2116         }
    2117         $this->StrokeAxis(false);
    2118 
    2119         // Stroke colored bands
    2120         $this->StrokeBands(DEPTH_BACK,$_csim);
    2121 
    2122         if( $this->grid_depth == DEPTH_BACK && !$_csim) {
    2123             $this->ygrid->Stroke();
    2124             $this->xgrid->Stroke();
    2125         }
    2126 
    2127         // Stroke Y2-axis
    2128         if( $this->y2axis != null && !$_csim) {
    2129             $this->y2axis->Stroke($this->xscale);
    2130             $this->y2grid->Stroke();
    2131         }
    2132 
    2133         // Stroke yn-axis
    2134         $n = count($this->ynaxis);
    2135         for( $i=0; $i < $n; ++$i ) {
    2136             $this->ynaxis[$i]->Stroke($this->xscale);
    2137         }
    2138 
    2139         $oldoff=$this->xscale->off;
    2140         if( substr($this->axtype,0,4) == 'text' ) {
    2141             if( $this->text_scale_abscenteroff > -1 ) {
    2142                 // For a text scale the scale factor is the number of pixel per step.
    2143                 // Hence we can use the scale factor as a substitute for number of pixels
    2144                 // per major scale step and use that in order to adjust the offset so that
    2145                 // an object of width "abscenteroff" becomes centered.
    2146                 $this->xscale->off += round($this->xscale->scale_factor/2)-round($this->text_scale_abscenteroff/2);
    2147             }
    2148             else {
    2149                 $this->xscale->off += ceil($this->xscale->scale_factor*$this->text_scale_off*$this->xscale->ticks->minor_step);
    2150             }
    2151         }
    2152 
    2153         if( $this->iDoClipping ) {
    2154             $oldimage = $this->img->CloneCanvasH();
    2155         }
    2156 
    2157         if( ! $this->y2orderback ) {
    2158             // Stroke all plots for Y1 axis
    2159             for($i=0; $i < count($this->plots); ++$i) {
    2160                 $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale);
    2161                 $this->plots[$i]->StrokeMargin($this->img);
    2162             }
    2163         }
    2164 
    2165         // Stroke all plots for Y2 axis
    2166         if( $this->y2scale != null ) {
    2167             for($i=0; $i< count($this->y2plots); ++$i ) {
    2168                 $this->y2plots[$i]->Stroke($this->img,$this->xscale,$this->y2scale);
    2169             }
    2170         }
    2171 
    2172         if( $this->y2orderback ) {
    2173             // Stroke all plots for Y1 axis
    2174             for($i=0; $i < count($this->plots); ++$i) {
    2175                 $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale);
    2176                 $this->plots[$i]->StrokeMargin($this->img);
    2177             }
    2178         }
    2179 
    2180         $n = count($this->ynaxis);
    2181         for( $i=0; $i < $n; ++$i ) {
    2182             $m = count($this->ynplots[$i]);
    2183             for( $j=0; $j < $m; ++$j ) {
    2184                 $this->ynplots[$i][$j]->Stroke($this->img,$this->xscale,$this->ynscale[$i]);
    2185                 $this->ynplots[$i][$j]->StrokeMargin($this->img);
    2186             }
    2187         }
    2188 
    2189         if( $this->iIconDepth == DEPTH_FRONT) {
    2190             $this->StrokeIcons();
    2191         }
    2192 
    2193         if( $this->iDoClipping ) {
    2194             // Clipping only supports graphs at 0 and 90 degrees
    2195             if( $this->img->a == 0 ) {
    2196                 $this->img->CopyCanvasH($oldimage,$this->img->img,
    2197                 $this->img->left_margin,$this->img->top_margin,
    2198                 $this->img->left_margin,$this->img->top_margin,
    2199                 $this->img->plotwidth+1,$this->img->plotheight);
    2200             }
    2201             elseif( $this->img->a == 90 ) {
    2202                 $adj = ($this->img->height - $this->img->width)/2;
    2203                 $this->img->CopyCanvasH($oldimage,$this->img->img,
    2204                 $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
    2205                 $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
    2206                 $this->img->plotheight+1,$this->img->plotwidth);
    2207             }
    2208             else {
    2209                 JpGraphError::RaiseL(25035,$this->img->a);//('You have enabled clipping. Cliping is only supported for graphs at 0 or 90 degrees rotation. Please adjust you current angle (='.$this->img->a.' degrees) or disable clipping.');
    2210             }
    2211             $this->img->Destroy();
    2212             $this->img->SetCanvasH($oldimage);
    2213         }
    2214 
    2215         $this->xscale->off=$oldoff;
    2216 
    2217         if( $this->grid_depth == DEPTH_FRONT && !$_csim ) {
    2218             $this->ygrid->Stroke();
    2219             $this->xgrid->Stroke();
    2220         }
    2221 
    2222         // Stroke colored bands
    2223         $this->StrokeBands(DEPTH_FRONT,$_csim);
    2224 
    2225         // Finally draw the axis again since some plots may have nagged
    2226         // the axis in the edges.
    2227         if( !$_csim ) {
    2228             $this->StrokeAxis();
    2229         }
    2230 
    2231         if( $this->y2scale != null && !$_csim ) {
    2232             $this->y2axis->Stroke($this->xscale,false);
    2233         }
    2234 
    2235         if( !$_csim ) {
    2236             $this->StrokePlotBox();
    2237         }
    2238 
    2239         // The titles and legends never gets rotated so make sure
    2240         // that the angle is 0 before stroking them
    2241         $aa = $this->img->SetAngle(0);
    2242         $this->StrokeTitles();
    2243         $this->footer->Stroke($this->img);
    2244         $this->legend->Stroke($this->img);
    2245         $this->img->SetAngle($aa);
    2246         $this->StrokeTexts();
    2247         $this->StrokeTables();
    2248 
    2249         if( !$_csim ) {
    2250 
    2251             $this->img->SetAngle($aa);
    2252 
    2253             // Draw an outline around the image map
    2254             if(_JPG_DEBUG) {
    2255                 $this->DisplayClientSideaImageMapAreas();
    2256             }
    2257 
    2258             // Should we do any final image transformation
    2259             if( $this->iImgTrans ) {
    2260                 if( !class_exists('ImgTrans',false) ) {
    2261                     require_once('jpgraph_imgtrans.php');
    2262                     //JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.');
    2263                 }
    2264 
    2265                 $tform = new ImgTrans($this->img->img);
    2266                 $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
    2267                 $this->iImgTransDirection,$this->iImgTransHighQ,
    2268                 $this->iImgTransMinSize,$this->iImgTransFillColor,
    2269                 $this->iImgTransBorder);
    2270             }
    2271 
    2272             // If the filename is given as the special "__handle"
    2273             // then the image handler is returned and the image is NOT
    2274             // streamed back
    2275             if( $aStrokeFileName == _IMG_HANDLER ) {
    2276                 return $this->img->img;
    2277             }
    2278             else {
    2279                 // Finally stream the generated picture
    2280                 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
    2281             }
    2282         }
     1455    function Stroke($aStrokeFileName="") {             
     1456
     1457        // Fist make a sanity check that user has specified a scale
     1458        if( empty($this->yscale) ) {
     1459            JpGraphError::RaiseL(25031);//('You must specify what scale to use with a call to Graph::SetScale().');
     1460        }
     1461
     1462        // Start by adjusting the margin so that potential titles will fit.
     1463        $this->AdjustMarginsForTitles();
     1464
     1465        // Setup scale constants
     1466        if( $this->yscale ) $this->yscale->InitConstants($this->img);
     1467        if( $this->xscale ) $this->xscale->InitConstants($this->img);
     1468        if( $this->y2scale ) $this->y2scale->InitConstants($this->img);
     1469       
     1470        $n=count($this->ynscale);
     1471        for($i=0; $i < $n; ++$i) {
     1472          if( $this->ynscale[$i] ) $this->ynscale[$i]->InitConstants($this->img);
     1473        }
     1474
     1475        // If the filename is the predefined value = '_csim_special_'
     1476        // we assume that the call to stroke only needs to do enough
     1477        // to correctly generate the CSIM maps.
     1478        // We use this variable to skip things we don't strictly need
     1479        // to do to generate the image map to improve performance
     1480        // a best we can. Therefor you will see a lot of tests !$_csim in the
     1481        // code below.
     1482        $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
     1483
     1484        // We need to know if we have stroked the plot in the
     1485        // GetCSIMareas. Otherwise the CSIM hasn't been generated
     1486        // and in the case of GetCSIM called before stroke to generate
     1487        // CSIM without storing an image to disk GetCSIM must call Stroke.
     1488        $this->iHasStroked = true;
     1489
     1490        // Do any pre-stroke adjustment that is needed by the different plot types
     1491        // (i.e bar plots want's to add an offset to the x-labels etc)
     1492        for($i=0; $i < count($this->plots) ; ++$i ) {
     1493            $this->plots[$i]->PreStrokeAdjust($this);
     1494            $this->plots[$i]->DoLegend($this);
     1495        }
     1496               
     1497        // Any plots on the second Y scale?
     1498        if( $this->y2scale != null ) {
     1499            for($i=0; $i<count($this->y2plots)  ; ++$i ) {
     1500                $this->y2plots[$i]->PreStrokeAdjust($this);
     1501                $this->y2plots[$i]->DoLegend($this);
     1502            }
     1503        }
     1504
     1505        // Any plots on the extra Y axises?
     1506        $n = count($this->ynaxis);
     1507        for($i=0; $i<$n ; ++$i ) {
     1508            if( $this->ynplots == null || $this->ynplots[$i] == null) {
     1509                JpGraphError::RaiseL(25032,$i);//("No plots for Y-axis nbr:$i");
     1510            }
     1511            $m = count($this->ynplots[$i]);
     1512            for($j=0; $j < $m; ++$j ) {
     1513                $this->ynplots[$i][$j]->PreStrokeAdjust($this);
     1514                $this->ynplots[$i][$j]->DoLegend($this);
     1515            }
     1516        }
     1517
     1518        // Bail out if any of the Y-axis not been specified and
     1519        // has no plots. (This means it is impossible to do autoscaling and
     1520        // no other scale was given so we can't possible draw anything). If you use manual
     1521        // scaling you also have to supply the tick steps as well.
     1522        if( (!$this->yscale->IsSpecified() && count($this->plots)==0) ||
     1523            ($this->y2scale!=null && !$this->y2scale->IsSpecified() && count($this->y2plots)==0) ) {
     1524            //$e = "n=".count($this->y2plots)."\n";
     1525            // $e = "Can't draw unspecified Y-scale.<br>\nYou have either:<br>\n";
     1526            // $e .= "1. Specified an Y axis for autoscaling but have not supplied any plots<br>\n";
     1527            // $e .= "2. Specified a scale manually but have forgot to specify the tick steps";
     1528            JpGraphError::RaiseL(25026);
     1529        }
     1530               
     1531        // Bail out if no plots and no specified X-scale
     1532        if( (!$this->xscale->IsSpecified() && count($this->plots)==0 && count($this->y2plots)==0) )
     1533            JpGraphError::RaiseL(25034);//("<strong>JpGraph: Can't draw unspecified X-scale.</strong><br>No plots.<br>");
     1534
     1535        //Check if we should autoscale y-axis
     1536        if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) {
     1537            list($min,$max) = $this->GetPlotsYMinMax($this->plots);
     1538            $lres = $this->GetLinesYMinMax($this->lines);
     1539            if( is_array($lres) ) {
     1540                list($linmin,$linmax) = $lres ;
     1541                $min = min($min,$linmin);
     1542                $max = max($max,$linmax);
     1543            }
     1544            $tres = $this->GetTextsYMinMax();
     1545            if( is_array($tres) ) {
     1546                list($tmin,$tmax) = $tres ;
     1547                $min = min($min,$tmin);
     1548                $max = max($max,$tmax);
     1549            }
     1550            $this->yscale->AutoScale($this->img,$min,$max,
     1551                                     $this->img->plotheight/$this->ytick_factor);
     1552        }
     1553        elseif( $this->yscale->IsSpecified() &&
     1554                ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) {
     1555            // The tick calculation will use the user suplied min/max values to determine
     1556            // the ticks. If auto_ticks is false the exact user specifed min and max
     1557            // values will be used for the scale.
     1558            // If auto_ticks is true then the scale might be slightly adjusted
     1559            // so that the min and max values falls on an even major step.
     1560            $min = $this->yscale->scale[0];
     1561            $max = $this->yscale->scale[1];
     1562            $this->yscale->AutoScale($this->img,$min,$max,
     1563                                     $this->img->plotheight/$this->ytick_factor,
     1564                                     $this->yscale->auto_ticks);
     1565
     1566            // Now make sure we show enough precision to accurate display the
     1567            // labels. If this is not done then the user might end up with
     1568            // a scale that might actually start with, say 13.5, butdue to rounding
     1569            // the scale label will ony show 14.
     1570            if( abs(floor($min)-$min) > 0 ) {
     1571               
     1572                // If the user has set a format then we bail out
     1573                if( $this->yscale->ticks->label_formatstr == '' && $this->yscale->ticks->label_dateformatstr == '' ) {
     1574                    $this->yscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
     1575                }
     1576            }
     1577        }
     1578
     1579        if( $this->y2scale != null) {
     1580            if( !$this->y2scale->IsSpecified() && count($this->y2plots)>0 ) {
     1581                list($min,$max) = $this->GetPlotsYMinMax($this->y2plots);
     1582
     1583                $lres = $this->GetLinesYMinMax($this->y2lines);
     1584                if( is_array($lres) ) {
     1585                    list($linmin,$linmax) = $lres ;
     1586                    $min = min($min,$linmin);
     1587                    $max = max($max,$linmax);
     1588                }
     1589                $tres = $this->GetTextsYMinMax(true);
     1590                if( is_array($tres) ) {
     1591                    list($tmin,$tmax) = $tres ;
     1592                    $min = min($min,$tmin);
     1593                    $max = max($max,$tmax);
     1594                }
     1595                $this->y2scale->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor);
     1596            }                   
     1597            elseif( $this->y2scale->IsSpecified() &&
     1598                    ( $this->y2scale->auto_ticks || !$this->y2scale->ticks->IsSpecified()) ) {
     1599                // The tick calculation will use the user suplied min/max values to determine
     1600                // the ticks. If auto_ticks is false the exact user specifed min and max
     1601                // values will be used for the scale.
     1602                // If auto_ticks is true then the scale might be slightly adjusted
     1603                // so that the min and max values falls on an even major step.
     1604                $min = $this->y2scale->scale[0];
     1605                $max = $this->y2scale->scale[1];
     1606                $this->y2scale->AutoScale($this->img,$min,$max,
     1607                                          $this->img->plotheight/$this->ytick_factor,
     1608                                          $this->y2scale->auto_ticks);
     1609
     1610            // Now make sure we show enough precision to accurate display the
     1611            // labels. If this is not done then the user might end up with
     1612            // a scale that might actually start with, say 13.5, butdue to rounding
     1613            // the scale label will ony show 14.
     1614            if( abs(floor($min)-$min) > 0 ) {
     1615               
     1616                // If the user has set a format then we bail out
     1617                if( $this->y2scale->ticks->label_formatstr == '' && $this->y2scale->ticks->label_dateformatstr == '' ) {
     1618                    $this->y2scale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
     1619                }
     1620            }
     1621
     1622            }
     1623        }
     1624                               
     1625        //
     1626        // Autoscale the extra Y-axises
     1627        //
     1628        $n = count($this->ynaxis);
     1629        for( $i=0; $i < $n; ++$i ) {
     1630          if( $this->ynscale[$i] != null) {
     1631            if( !$this->ynscale[$i]->IsSpecified() && count($this->ynplots[$i])>0 ) {
     1632              list($min,$max) = $this->GetPlotsYMinMax($this->ynplots[$i]);
     1633              $this->ynscale[$i]->AutoScale($this->img,$min,$max,$this->img->plotheight/$this->ytick_factor);
     1634            }                   
     1635            elseif( $this->ynscale[$i]->IsSpecified() &&
     1636                    ( $this->ynscale[$i]->auto_ticks || !$this->ynscale[$i]->ticks->IsSpecified()) ) {
     1637                // The tick calculation will use the user suplied min/max values to determine
     1638                // the ticks. If auto_ticks is false the exact user specifed min and max
     1639                // values will be used for the scale.
     1640                // If auto_ticks is true then the scale might be slightly adjusted
     1641                // so that the min and max values falls on an even major step.
     1642              $min = $this->ynscale[$i]->scale[0];
     1643              $max = $this->ynscale[$i]->scale[1];
     1644              $this->ynscale[$i]->AutoScale($this->img,$min,$max,
     1645                                            $this->img->plotheight/$this->ytick_factor,
     1646                                            $this->ynscale[$i]->auto_ticks);
     1647
     1648              // Now make sure we show enough precision to accurate display the
     1649              // labels. If this is not done then the user might end up with
     1650              // a scale that might actually start with, say 13.5, butdue to rounding
     1651              // the scale label will ony show 14.
     1652              if( abs(floor($min)-$min) > 0 ) {
     1653               
     1654                  // If the user has set a format then we bail out
     1655                  if( $this->ynscale[$i]->ticks->label_formatstr == '' && $this->ynscale[$i]->ticks->label_dateformatstr == '' ) {
     1656                      $this->ynscale[$i]->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
     1657                  }
     1658              }
     1659
     1660            }
     1661          }
     1662        }
     1663               
     1664        //Check if we should autoscale x-axis
     1665        if( !$this->xscale->IsSpecified() ) {
     1666            if( substr($this->axtype,0,4) == "text" ) {
     1667                $max=0;
     1668                $n = count($this->plots);
     1669                for($i=0; $i < $n; ++$i ) {
     1670                    $p = $this->plots[$i];
     1671                    // We need some unfortunate sub class knowledge here in order
     1672                    // to increase number of data points in case it is a line plot
     1673                    // which has the barcenter set. If not it could mean that the
     1674                    // last point of the data is outside the scale since the barcenter
     1675                    // settings means that we will shift the entire plot half a tick step
     1676                    // to the right in oder to align with the center of the bars.
     1677                    if( class_exists('BarPlot',false) ) {
     1678                        $cl = strtolower(get_class($p));
     1679                        if( (class_exists('BarPlot',false) && ($p instanceof BarPlot)) ||
     1680                            empty($p->barcenter) )
     1681                            $max=max($max,$p->numpoints-1);
     1682                        else {
     1683                            $max=max($max,$p->numpoints);
     1684                        }
     1685                    }
     1686                    else {
     1687                        if( empty($p->barcenter) ) {
     1688                            $max=max($max,$p->numpoints-1);
     1689                        }
     1690                        else {
     1691                            $max=max($max,$p->numpoints);
     1692                        }
     1693                    }
     1694                }
     1695                $min=0;
     1696                if( $this->y2axis != null ) {
     1697                    foreach( $this->y2plots as $p ) {
     1698                        $max=max($max,$p->numpoints-1);
     1699                    }               
     1700                }
     1701                $n = count($this->ynaxis);
     1702                for( $i=0; $i < $n; ++$i ) {
     1703                    if( $this->ynaxis[$i] != null) {
     1704                        foreach( $this->ynplots[$i] as $p ) {
     1705                            $max=max($max,$p->numpoints-1);
     1706                        }                   
     1707                    }
     1708                }
     1709               
     1710                $this->xscale->Update($this->img,$min,$max);
     1711                $this->xscale->ticks->Set($this->xaxis->tick_step,1);
     1712                $this->xscale->ticks->SupressMinorTickMarks();
     1713            }
     1714            else {
     1715                list($min,$max) = $this->GetXMinMax();
     1716
     1717                $lres = $this->GetLinesXMinMax($this->lines);
     1718                if( $lres ) {
     1719                    list($linmin,$linmax) = $lres ;
     1720                    $min = min($min,$linmin);
     1721                    $max = max($max,$linmax);
     1722                }
     1723
     1724                $lres = $this->GetLinesXMinMax($this->y2lines);
     1725                if( $lres ) {
     1726                    list($linmin,$linmax) = $lres ;
     1727                    $min = min($min,$linmin);
     1728                    $max = max($max,$linmax);
     1729                }
     1730
     1731                $tres = $this->GetTextsXMinMax();
     1732                if( $tres ) {
     1733                    list($tmin,$tmax) = $tres ;
     1734                    $min = min($min,$tmin);
     1735                    $max = max($max,$tmax);
     1736                }
     1737
     1738                $tres = $this->GetTextsXMinMax(true);
     1739                if( $tres ) {
     1740                    list($tmin,$tmax) = $tres ;
     1741                    $min = min($min,$tmin);
     1742                    $max = max($max,$tmax);
     1743                }
     1744
     1745                $this->xscale->AutoScale($this->img,$min,$max,round($this->img->plotwidth/$this->xtick_factor));
     1746            }
     1747                       
     1748            //Adjust position of y-axis and y2-axis to minimum/maximum of x-scale
     1749            if( !is_numeric($this->yaxis->pos) && !is_string($this->yaxis->pos) )
     1750                $this->yaxis->SetPos($this->xscale->GetMinVal());
     1751            if( $this->y2axis != null ) {
     1752                if( !is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos) )
     1753                    $this->y2axis->SetPos($this->xscale->GetMaxVal());
     1754                $this->y2axis->SetTitleSide(SIDE_RIGHT);
     1755            }
     1756            $n = count($this->ynaxis);
     1757            $nY2adj = $this->y2axis != null ? $this->iYAxisDeltaPos : 0;
     1758            for( $i=0; $i < $n; ++$i ) {
     1759                if( $this->ynaxis[$i] != null ) {
     1760                    if( !is_numeric($this->ynaxis[$i]->pos) && !is_string($this->ynaxis[$i]->pos) ) {
     1761                        $this->ynaxis[$i]->SetPos($this->xscale->GetMaxVal());
     1762                  $this->ynaxis[$i]->SetPosAbsDelta($i*$this->iYAxisDeltaPos + $nY2adj);
     1763                    }
     1764                    $this->ynaxis[$i]->SetTitleSide(SIDE_RIGHT);
     1765                }
     1766            }
     1767
     1768        }       
     1769        elseif( $this->xscale->IsSpecified() && 
     1770                ( $this->xscale->auto_ticks || !$this->xscale->ticks->IsSpecified()) ) {
     1771            // The tick calculation will use the user suplied min/max values to determine
     1772            // the ticks. If auto_ticks is false the exact user specifed min and max
     1773            // values will be used for the scale.
     1774            // If auto_ticks is true then the scale might be slightly adjusted
     1775            // so that the min and max values falls on an even major step.
     1776            $min = $this->xscale->scale[0];
     1777            $max = $this->xscale->scale[1];
     1778            $this->xscale->AutoScale($this->img,$min,$max,
     1779                                     round($this->img->plotwidth/$this->xtick_factor),
     1780                                     false);
     1781
     1782            // Now make sure we show enough precision to accurate display the
     1783            // labels. If this is not done then the user might end up with
     1784            // a scale that might actually start with, say 13.5, butdue to rounding
     1785            // the scale label will ony show 14.
     1786            if( abs(floor($min)-$min) > 0 ) {
     1787               
     1788                // If the user has set a format then we bail out
     1789                if( $this->xscale->ticks->label_formatstr == '' && $this->xscale->ticks->label_dateformatstr == '' ) {
     1790                    $this->xscale->ticks->precision = abs( floor(log10( abs(floor($min)-$min))) )+1;
     1791                }
     1792            }
     1793
     1794
     1795            if( $this->y2axis != null ) {
     1796                if( !is_numeric($this->y2axis->pos) && !is_string($this->y2axis->pos) )
     1797                    $this->y2axis->SetPos($this->xscale->GetMaxVal());
     1798                $this->y2axis->SetTitleSide(SIDE_RIGHT);
     1799            }
     1800
     1801        }
     1802               
     1803        // If we have a negative values and x-axis position is at 0
     1804        // we need to supress the first and possible the last tick since
     1805        // they will be drawn on top of the y-axis (and possible y2 axis)
     1806        // The test below might seem strange the reasone being that if
     1807        // the user hasn't specified a value for position this will not
     1808        // be set until we do the stroke for the axis so as of now it
     1809        // is undefined.
     1810        // For X-text scale we ignore all this since the tick are usually
     1811        // much further in and not close to the Y-axis. Hence the test
     1812        // for 'text'   
     1813
     1814        if( ($this->yaxis->pos==$this->xscale->GetMinVal() ||
     1815             (is_string($this->yaxis->pos) && $this->yaxis->pos=='min')) && 
     1816            !is_numeric($this->xaxis->pos) && $this->yscale->GetMinVal() < 0 &&
     1817            substr($this->axtype,0,4) != 'text' && $this->xaxis->pos!="min" ) {
     1818
     1819            //$this->yscale->ticks->SupressZeroLabel(false);
     1820            $this->xscale->ticks->SupressFirst();
     1821            if( $this->y2axis != null ) {
     1822                $this->xscale->ticks->SupressLast();
     1823            }
     1824        }
     1825        elseif( !is_numeric($this->yaxis->pos) && $this->yaxis->pos=='max' ) {
     1826            $this->xscale->ticks->SupressLast();
     1827        }
     1828       
     1829
     1830        if( !$_csim ) {
     1831            $this->StrokePlotArea();
     1832            if( $this->iIconDepth == DEPTH_BACK ) {
     1833                $this->StrokeIcons();
     1834            }
     1835        }
     1836        $this->StrokeAxis(false);
     1837
     1838        // Stroke bands
     1839        if( $this->bands != null && !$_csim)
     1840            for($i=0; $i < count($this->bands); ++$i) {
     1841                // Stroke all bands that asks to be in the background
     1842                if( $this->bands[$i]->depth == DEPTH_BACK )
     1843                    $this->bands[$i]->Stroke($this->img,$this->xscale,$this->yscale);
     1844            }
     1845
     1846        if( $this->y2bands != null && $this->y2scale != null && !$_csim )
     1847            for($i=0; $i < count($this->y2bands); ++$i) {
     1848                // Stroke all bands that asks to be in the foreground
     1849                if( $this->y2bands[$i]->depth == DEPTH_BACK )
     1850                    $this->y2bands[$i]->Stroke($this->img,$this->xscale,$this->y2scale);
     1851            }
     1852
     1853
     1854        if( $this->grid_depth == DEPTH_BACK && !$_csim) {
     1855            $this->ygrid->Stroke();
     1856            $this->xgrid->Stroke();
     1857        }
     1858                               
     1859        // Stroke Y2-axis
     1860        if( $this->y2axis != null && !$_csim) {         
     1861            $this->y2axis->Stroke($this->xscale);                               
     1862            $this->y2grid->Stroke();
     1863        }
     1864
     1865        // Stroke yn-axis
     1866        $n = count($this->ynaxis);
     1867        for( $i=0; $i < $n; ++$i ) {
     1868            $this->ynaxis[$i]->Stroke($this->xscale);                           
     1869        }
     1870
     1871        $oldoff=$this->xscale->off;
     1872        if(substr($this->axtype,0,4)=="text") {
     1873            if( $this->text_scale_abscenteroff > -1 ) {
     1874                // For a text scale the scale factor is the number of pixel per step.
     1875                // Hence we can use the scale factor as a substitute for number of pixels
     1876                // per major scale step and use that in order to adjust the offset so that
     1877                // an object of width "abscenteroff" becomes centered.
     1878                $this->xscale->off += round($this->xscale->scale_factor/2)-round($this->text_scale_abscenteroff/2);
     1879            }
     1880            else {
     1881                $this->xscale->off +=
     1882                    ceil($this->xscale->scale_factor*$this->text_scale_off*$this->xscale->ticks->minor_step);
     1883            }
     1884        }
     1885
     1886        if( $this->iDoClipping ) {
     1887            $oldimage = $this->img->CloneCanvasH();
     1888        }
     1889
     1890        if( ! $this->y2orderback ) {
     1891            // Stroke all plots for Y1 axis
     1892            for($i=0; $i < count($this->plots); ++$i) {
     1893                $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale);
     1894                $this->plots[$i]->StrokeMargin($this->img);
     1895            }                                           
     1896        }
     1897
     1898        // Stroke all plots for Y2 axis
     1899        if( $this->y2scale != null )
     1900            for($i=0; $i< count($this->y2plots); ++$i ) {       
     1901                $this->y2plots[$i]->Stroke($this->img,$this->xscale,$this->y2scale);
     1902            }           
     1903
     1904        if( $this->y2orderback ) {
     1905            // Stroke all plots for Y1 axis
     1906            for($i=0; $i < count($this->plots); ++$i) {
     1907                $this->plots[$i]->Stroke($this->img,$this->xscale,$this->yscale);
     1908                $this->plots[$i]->StrokeMargin($this->img);
     1909            }                                           
     1910        }
     1911
     1912        $n = count($this->ynaxis);
     1913        for( $i=0; $i < $n; ++$i ) {
     1914            $m = count($this->ynplots[$i]);
     1915            for( $j=0; $j < $m; ++$j ) {
     1916                $this->ynplots[$i][$j]->Stroke($this->img,$this->xscale,$this->ynscale[$i]);
     1917                $this->ynplots[$i][$j]->StrokeMargin($this->img);
     1918            }
     1919        }
     1920
     1921        if( $this->iIconDepth == DEPTH_FRONT) {
     1922            $this->StrokeIcons();
     1923        }
     1924       
     1925        if( $this->iDoClipping ) {
     1926            // Clipping only supports graphs at 0 and 90 degrees
     1927            if( $this->img->a == 0 ) {
     1928                $this->img->CopyCanvasH($oldimage,$this->img->img,
     1929                                        $this->img->left_margin,$this->img->top_margin,
     1930                                        $this->img->left_margin,$this->img->top_margin,
     1931                                        $this->img->plotwidth+1,$this->img->plotheight);
     1932            }
     1933            elseif( $this->img->a == 90 ) {
     1934                $adj = ($this->img->height - $this->img->width)/2;
     1935                $this->img->CopyCanvasH($oldimage,$this->img->img,
     1936                                        $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
     1937                                        $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
     1938                                        $this->img->plotheight+1,$this->img->plotwidth);
     1939            }
     1940            else {
     1941                JpGraphError::RaiseL(25035,$this->img->a);//('You have enabled clipping. Cliping is only supported for graphs at 0 or 90 degrees rotation. Please adjust you current angle (='.$this->img->a.' degrees) or disable clipping.');
     1942            }
     1943            $this->img->Destroy();
     1944            $this->img->SetCanvasH($oldimage);
     1945        }
     1946
     1947        $this->xscale->off=$oldoff;
     1948               
     1949        if( $this->grid_depth == DEPTH_FRONT && !$_csim ) {
     1950            $this->ygrid->Stroke();
     1951            $this->xgrid->Stroke();
     1952        }
     1953
     1954        // Stroke bands
     1955        if( $this->bands!= null )
     1956            for($i=0; $i < count($this->bands); ++$i) {
     1957                // Stroke all bands that asks to be in the foreground
     1958                if( $this->bands[$i]->depth == DEPTH_FRONT )
     1959                    $this->bands[$i]->Stroke($this->img,$this->xscale,$this->yscale);
     1960            }
     1961
     1962        if( $this->y2bands!= null && $this->y2scale != null )
     1963            for($i=0; $i < count($this->y2bands); ++$i) {
     1964                // Stroke all bands that asks to be in the foreground
     1965                if( $this->y2bands[$i]->depth == DEPTH_FRONT )
     1966                    $this->y2bands[$i]->Stroke($this->img,$this->xscale,$this->y2scale);
     1967            }
     1968
     1969
     1970        // Stroke any lines added
     1971        if( $this->lines != null ) {
     1972            for($i=0; $i < count($this->lines); ++$i) {
     1973                $this->lines[$i]->Stroke($this->img,$this->xscale,$this->yscale);
     1974                $this->lines[$i]->DoLegend($this);
     1975            }
     1976        }
     1977
     1978        if( $this->y2lines != null && $this->y2scale != null ) {
     1979            for($i=0; $i < count($this->y2lines); ++$i) {
     1980                $this->y2lines[$i]->Stroke($this->img,$this->xscale,$this->y2scale);
     1981                $this->y2lines[$i]->DoLegend($this);
     1982            }
     1983        }
     1984
     1985        // Finally draw the axis again since some plots may have nagged
     1986        // the axis in the edges.
     1987        if( !$_csim ) {
     1988            $this->StrokeAxis();
     1989        }
     1990
     1991        if( $this->y2scale != null && !$_csim )
     1992            $this->y2axis->Stroke($this->xscale,false);         
     1993               
     1994        if( !$_csim ) {
     1995            $this->StrokePlotBox();
     1996        }
     1997               
     1998        // The titles and legends never gets rotated so make sure
     1999        // that the angle is 0 before stroking them                             
     2000        $aa = $this->img->SetAngle(0);
     2001        $this->StrokeTitles();
     2002        $this->footer->Stroke($this->img);
     2003        $this->legend->Stroke($this->img);             
     2004        $this->img->SetAngle($aa);     
     2005        $this->StrokeTexts();   
     2006        $this->StrokeTables();
     2007
     2008        if( !$_csim ) {
     2009
     2010            $this->img->SetAngle($aa); 
     2011                       
     2012            // Draw an outline around the image map     
     2013            if(_JPG_DEBUG) {
     2014                $this->DisplayClientSideaImageMapAreas();               
     2015            }
     2016           
     2017            // Should we do any final image transformation
     2018            if( $this->iImgTrans ) {
     2019                if( !class_exists('ImgTrans',false) ) {
     2020                    require_once('jpgraph_imgtrans.php');
     2021                    //JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.');
     2022                }
     2023               
     2024                $tform = new ImgTrans($this->img->img);
     2025                $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
     2026                                                 $this->iImgTransDirection,$this->iImgTransHighQ,
     2027                                                 $this->iImgTransMinSize,$this->iImgTransFillColor,
     2028                                                 $this->iImgTransBorder);
     2029            }
     2030
     2031            // If the filename is given as the special "__handle"
     2032            // then the image handler is returned and the image is NOT
     2033            // streamed back
     2034            if( $aStrokeFileName == _IMG_HANDLER ) {
     2035                return $this->img->img;
     2036            }
     2037            else {
     2038                // Finally stream the generated picture                                 
     2039                $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);               
     2040            }
     2041        }
    22832042    }
    22842043
    22852044    function SetAxisLabelBackground($aType,$aXFColor='lightgray',$aXColor='black',$aYFColor='lightgray',$aYColor='black') {
    2286         $this->iAxisLblBgType = $aType;
    2287         $this->iXAxisLblBgFillColor = $aXFColor;
    2288         $this->iXAxisLblBgColor = $aXColor;
    2289         $this->iYAxisLblBgFillColor = $aYFColor;
    2290         $this->iYAxisLblBgColor = $aYColor;
    2291     }
     2045        $this->iAxisLblBgType = $aType;
     2046        $this->iXAxisLblBgFillColor = $aXFColor;
     2047        $this->iXAxisLblBgColor = $aXColor;
     2048        $this->iYAxisLblBgFillColor = $aYFColor;
     2049        $this->iYAxisLblBgColor = $aYColor;
     2050    }
     2051
     2052//---------------
     2053// PRIVATE METHODS     
    22922054
    22932055    function StrokeAxisLabelBackground() {
    2294         // Types
    2295         // 0 = No background
    2296         // 1 = Only X-labels, length of axis
    2297         // 2 = Only Y-labels, length of axis
    2298         // 3 = As 1 but extends to width of graph
    2299         // 4 = As 2 but extends to height of graph
    2300         // 5 = Combination of 3 & 4
    2301         // 6 = Combination of 1 & 2
    2302 
    2303         $t = $this->iAxisLblBgType ;
    2304         if( $t < 1 ) return;
    2305 
    2306         // Stroke optional X-axis label background color
    2307         if( $t == 1 || $t == 3 || $t == 5 || $t == 6 ) {
    2308             $this->img->PushColor($this->iXAxisLblBgFillColor);
    2309             if( $t == 1 || $t == 6 ) {
    2310                 $xl = $this->img->left_margin;
    2311                 $yu = $this->img->height - $this->img->bottom_margin + 1;
    2312                 $xr = $this->img->width - $this->img->right_margin ;
    2313                 $yl = $this->img->height-1-$this->frame_weight;
    2314             }
    2315             else { // t==3 || t==5
    2316                 $xl = $this->frame_weight;
    2317                 $yu = $this->img->height - $this->img->bottom_margin + 1;
    2318                 $xr = $this->img->width - 1 - $this->frame_weight;
    2319                 $yl = $this->img->height-1-$this->frame_weight;
    2320             }
    2321 
    2322             $this->img->FilledRectangle($xl,$yu,$xr,$yl);
    2323             $this->img->PopColor();
    2324 
    2325             // Check if we should add the vertical lines at left and right edge
    2326             if( $this->iXAxisLblBgColor !== '' ) {
    2327                 // Hardcode to one pixel wide
    2328                 $this->img->SetLineWeight(1);
    2329                 $this->img->PushColor($this->iXAxisLblBgColor);
    2330                 if( $t == 1 || $t == 6 ) {
    2331                     $this->img->Line($xl,$yu,$xl,$yl);
    2332                     $this->img->Line($xr,$yu,$xr,$yl);
    2333                 }
    2334                 else {
    2335                     $xl = $this->img->width - $this->img->right_margin ;
    2336                     $this->img->Line($xl,$yu-1,$xr,$yu-1);
    2337                 }
    2338                 $this->img->PopColor();
    2339             }
    2340         }
    2341 
    2342         if( $t == 2 || $t == 4 || $t == 5 || $t == 6 ) {
    2343             $this->img->PushColor($this->iYAxisLblBgFillColor);
    2344             if( $t == 2 || $t == 6 ) {
    2345                 $xl = $this->frame_weight;
    2346                 $yu = $this->frame_weight+$this->img->top_margin;
    2347                 $xr = $this->img->left_margin - 1;
    2348                 $yl = $this->img->height - $this->img->bottom_margin + 1;
    2349             }
    2350             else {
    2351                 $xl = $this->frame_weight;
    2352                 $yu = $this->frame_weight;
    2353                 $xr = $this->img->left_margin - 1;
    2354                 $yl = $this->img->height-1-$this->frame_weight;
    2355             }
    2356 
    2357             $this->img->FilledRectangle($xl,$yu,$xr,$yl);
    2358             $this->img->PopColor();
    2359 
    2360             // Check if we should add the vertical lines at left and right edge
    2361             if( $this->iXAxisLblBgColor !== '' ) {
    2362                 $this->img->PushColor($this->iXAxisLblBgColor);
    2363                 if( $t == 2 || $t == 6 ) {
    2364                     $this->img->Line($xl,$yu-1,$xr,$yu-1);
    2365                     $this->img->Line($xl,$yl-1,$xr,$yl-1);
    2366                 }
    2367                 else {
    2368                     $this->img->Line($xr+1,$yu,$xr+1,$this->img->top_margin);
    2369                 }
    2370                 $this->img->PopColor();
    2371             }
    2372 
    2373         }
     2056        // Types
     2057        // 0 = No background
     2058        // 1 = Only X-labels, length of axis
     2059        // 2 = Only Y-labels, length of axis
     2060        // 3 = As 1 but extends to width of graph
     2061        // 4 = As 2 but extends to height of graph
     2062        // 5 = Combination of 3 & 4
     2063        // 6 = Combination of 1 & 2
     2064 
     2065        $t = $this->iAxisLblBgType ;
     2066        if( $t < 1 ) return;
     2067        // Stroke optional X-axis label background color
     2068        if( $t == 1 || $t == 3 || $t == 5 || $t == 6 ) {
     2069            $this->img->PushColor($this->iXAxisLblBgFillColor);
     2070            if( $t == 1 || $t == 6 ) {
     2071                $xl = $this->img->left_margin;
     2072                $yu = $this->img->height - $this->img->bottom_margin + 1;
     2073                $xr = $this->img->width - $this->img->right_margin ;
     2074                $yl = $this->img->height-1-$this->frame_weight;
     2075            }
     2076            else { // t==3 || t==5
     2077                $xl = $this->frame_weight;
     2078                $yu = $this->img->height - $this->img->bottom_margin + 1;
     2079                $xr = $this->img->width - 1 - $this->frame_weight;
     2080                $yl = $this->img->height-1-$this->frame_weight;
     2081            }
     2082
     2083            $this->img->FilledRectangle($xl,$yu,$xr,$yl);
     2084            $this->img->PopColor();
     2085
     2086            // Check if we should add the vertical lines at left and right edge
     2087            if( $this->iXAxisLblBgColor !== '' ) {
     2088                // Hardcode to one pixel wide
     2089                $this->img->SetLineWeight(1);
     2090                $this->img->PushColor($this->iXAxisLblBgColor);
     2091                if( $t == 1 || $t == 6 ) {
     2092                    $this->img->Line($xl,$yu,$xl,$yl);
     2093                    $this->img->Line($xr,$yu,$xr,$yl);
     2094                }
     2095                else {
     2096                    $xl = $this->img->width - $this->img->right_margin ;
     2097                    $this->img->Line($xl,$yu-1,$xr,$yu-1);
     2098                }
     2099                $this->img->PopColor();
     2100            }
     2101        }
     2102
     2103        if( $t == 2 || $t == 4 || $t == 5 || $t == 6 ) {
     2104            $this->img->PushColor($this->iYAxisLblBgFillColor);
     2105            if( $t == 2 || $t == 6 ) {     
     2106                $xl = $this->frame_weight;
     2107                $yu = $this->frame_weight+$this->img->top_margin;
     2108                $xr = $this->img->left_margin - 1;
     2109                $yl = $this->img->height - $this->img->bottom_margin + 1;
     2110            }
     2111            else {
     2112                $xl = $this->frame_weight;
     2113                $yu = $this->frame_weight;
     2114                $xr = $this->img->left_margin - 1;
     2115                $yl = $this->img->height-1-$this->frame_weight;
     2116            }
     2117
     2118            $this->img->FilledRectangle($xl,$yu,$xr,$yl);
     2119            $this->img->PopColor();
     2120
     2121            // Check if we should add the vertical lines at left and right edge
     2122            if( $this->iXAxisLblBgColor !== '' ) {
     2123                $this->img->PushColor($this->iXAxisLblBgColor);
     2124                if( $t == 2 || $t == 6 ) {
     2125                    $this->img->Line($xl,$yu-1,$xr,$yu-1);
     2126                    $this->img->Line($xl,$yl-1,$xr,$yl-1);                 
     2127                }
     2128                else {
     2129                    $this->img->Line($xr+1,$yu,$xr+1,$this->img->top_margin);               
     2130                }
     2131                $this->img->PopColor();
     2132            }
     2133
     2134        }
    23742135    }
    23752136
    23762137    function StrokeAxis($aStrokeLabels=true) {
    2377 
    2378         if( $aStrokeLabels ) {
    2379             $this->StrokeAxisLabelBackground();
    2380         }
    2381 
    2382         // Stroke axis
    2383         if( $this->iAxisStyle != AXSTYLE_SIMPLE ) {
    2384             switch( $this->iAxisStyle ) {
    2385                 case AXSTYLE_BOXIN :
    2386                     $toppos = SIDE_DOWN;
    2387                     $bottompos = SIDE_UP;
    2388                     $leftpos = SIDE_RIGHT;
    2389                     $rightpos = SIDE_LEFT;
    2390                     break;
    2391                 case AXSTYLE_BOXOUT :
    2392                     $toppos = SIDE_UP;
    2393                     $bottompos = SIDE_DOWN;
    2394                     $leftpos = SIDE_LEFT;
    2395                     $rightpos = SIDE_RIGHT;
    2396                     break;
    2397                 case AXSTYLE_YBOXIN:
    2398                     $toppos = FALSE;
    2399                     $bottompos = SIDE_UP;
    2400                     $leftpos = SIDE_RIGHT;
    2401                     $rightpos = SIDE_LEFT;
    2402                     break;
    2403                 case AXSTYLE_YBOXOUT:
    2404                     $toppos = FALSE;
    2405                     $bottompos = SIDE_DOWN;
    2406                     $leftpos = SIDE_LEFT;
    2407                     $rightpos = SIDE_RIGHT;
    2408                     break;
    2409                 default:
    2410                     JpGRaphError::RaiseL(25036,$this->iAxisStyle); //('Unknown AxisStyle() : '.$this->iAxisStyle);
    2411                     break;
    2412             }
    2413 
    2414             // By default we hide the first label so it doesn't cross the
    2415             // Y-axis in case the positon hasn't been set by the user.
    2416             // However, if we use a box we always want the first value
    2417             // displayed so we make sure it will be displayed.
    2418             $this->xscale->ticks->SupressFirst(false);
    2419 
    2420             // Now draw the bottom X-axis
    2421             $this->xaxis->SetPos('min');
    2422             $this->xaxis->SetLabelSide(SIDE_DOWN);
    2423             $this->xaxis->scale->ticks->SetSide($bottompos);
    2424             $this->xaxis->Stroke($this->yscale,$aStrokeLabels);
    2425 
    2426             if( $toppos !== FALSE ) {
    2427                 // We also want a top X-axis
    2428                 $this->xaxis = $this->xaxis;
    2429                 $this->xaxis->SetPos('max');
    2430                 $this->xaxis->SetLabelSide(SIDE_UP);
    2431                 // No title for the top X-axis
    2432                 if( $aStrokeLabels ) {
    2433                     $this->xaxis->title->Set('');
    2434                 }
    2435                 $this->xaxis->scale->ticks->SetSide($toppos);
    2436                 $this->xaxis->Stroke($this->yscale,$aStrokeLabels);
    2437             }
    2438 
    2439             // Stroke the left Y-axis
    2440             $this->yaxis->SetPos('min');
    2441             $this->yaxis->SetLabelSide(SIDE_LEFT);
    2442             $this->yaxis->scale->ticks->SetSide($leftpos);
    2443             $this->yaxis->Stroke($this->xscale,$aStrokeLabels);
    2444 
    2445             // Stroke the  right Y-axis
    2446             $this->yaxis->SetPos('max');
    2447             // No title for the right side
    2448             if( $aStrokeLabels ) {
    2449                 $this->yaxis->title->Set('');
    2450             }
    2451             $this->yaxis->SetLabelSide(SIDE_RIGHT);
    2452             $this->yaxis->scale->ticks->SetSide($rightpos);
    2453             $this->yaxis->Stroke($this->xscale,$aStrokeLabels);
    2454         }
    2455         else {
    2456             $this->xaxis->Stroke($this->yscale,$aStrokeLabels);
    2457             $this->yaxis->Stroke($this->xscale,$aStrokeLabels);
    2458         }
     2138       
     2139        if( $aStrokeLabels ) {
     2140            $this->StrokeAxisLabelBackground();
     2141        }
     2142
     2143        // Stroke axis
     2144        if( $this->iAxisStyle != AXSTYLE_SIMPLE ) {
     2145            switch( $this->iAxisStyle ) {
     2146                case AXSTYLE_BOXIN :
     2147                    $toppos = SIDE_DOWN;
     2148                    $bottompos = SIDE_UP;
     2149                    $leftpos = SIDE_RIGHT;
     2150                    $rightpos = SIDE_LEFT;
     2151                    break;
     2152                case AXSTYLE_BOXOUT :
     2153                    $toppos = SIDE_UP;
     2154                    $bottompos = SIDE_DOWN;         
     2155                    $leftpos = SIDE_LEFT;
     2156                    $rightpos = SIDE_RIGHT;
     2157                    break;
     2158                case AXSTYLE_YBOXIN:
     2159                    $toppos = FALSE;
     2160                    $bottompos = SIDE_UP;
     2161                    $leftpos = SIDE_RIGHT;
     2162                    $rightpos = SIDE_LEFT;
     2163                    break;
     2164                case AXSTYLE_YBOXOUT:
     2165                    $toppos = FALSE;
     2166                    $bottompos = SIDE_DOWN;         
     2167                    $leftpos = SIDE_LEFT;
     2168                    $rightpos = SIDE_RIGHT;
     2169                    break;
     2170                default:
     2171                    JpGRaphError::RaiseL(25036,$this->iAxisStyle); //('Unknown AxisStyle() : '.$this->iAxisStyle);
     2172                    break;
     2173            }
     2174           
     2175            // By default we hide the first label so it doesn't cross the
     2176            // Y-axis in case the positon hasn't been set by the user.
     2177            // However, if we use a box we always want the first value
     2178            // displayed so we make sure it will be displayed.
     2179            $this->xscale->ticks->SupressFirst(false);   
     2180
     2181            // Now draw the bottom X-axis
     2182            $this->xaxis->SetPos('min');
     2183            $this->xaxis->SetLabelSide(SIDE_DOWN);
     2184            $this->xaxis->scale->ticks->SetSide($bottompos);
     2185            $this->xaxis->Stroke($this->yscale,$aStrokeLabels);
     2186
     2187            if( $toppos !== FALSE ) {
     2188                // We also want a top X-axis
     2189                $this->xaxis = $this->xaxis;
     2190                $this->xaxis->SetPos('max');
     2191                $this->xaxis->SetLabelSide(SIDE_UP);
     2192                // No title for the top X-axis
     2193                if( $aStrokeLabels ) {
     2194                    $this->xaxis->title->Set('');
     2195                }
     2196                $this->xaxis->scale->ticks->SetSide($toppos);
     2197                $this->xaxis->Stroke($this->yscale,$aStrokeLabels);
     2198            }
     2199
     2200            // Stroke the left Y-axis
     2201            $this->yaxis->SetPos('min');
     2202            $this->yaxis->SetLabelSide(SIDE_LEFT);
     2203            $this->yaxis->scale->ticks->SetSide($leftpos);
     2204            $this->yaxis->Stroke($this->xscale,$aStrokeLabels);
     2205
     2206            // Stroke the  right Y-axis
     2207            $this->yaxis->SetPos('max');
     2208            // No title for the right side
     2209            if( $aStrokeLabels ) {
     2210                $this->yaxis->title->Set('');
     2211            }
     2212            $this->yaxis->SetLabelSide(SIDE_RIGHT);
     2213            $this->yaxis->scale->ticks->SetSide($rightpos);
     2214            $this->yaxis->Stroke($this->xscale,$aStrokeLabels); 
     2215        }
     2216        else {
     2217            $this->xaxis->Stroke($this->yscale,$aStrokeLabels);
     2218            $this->yaxis->Stroke($this->xscale,$aStrokeLabels);         
     2219        }
    24592220    }
    24602221
     
    24622223    // Private helper function for backgound image
    24632224    static function LoadBkgImage($aImgFormat='',$aFile='',$aImgStr='') {
    2464         if( $aImgStr != '' ) {
    2465             return Image::CreateFromString($aImgStr);
    2466         }
    2467 
    2468         // Remove case sensitivity and setup appropriate function to create image
    2469         // Get file extension. This should be the LAST '.' separated part of the filename
    2470         $e = explode('.',$aFile);
    2471         $ext = strtolower($e[count($e)-1]);
    2472         if ($ext == "jpeg")  {
    2473             $ext = "jpg";
    2474         }
    2475 
    2476         if( trim($ext) == '' ) {
    2477             $ext = 'png';  // Assume PNG if no extension specified
    2478         }
    2479 
    2480         if( $aImgFormat == '' ) {
    2481             $imgtag = $ext;
    2482         }
    2483         else {
    2484             $imgtag = $aImgFormat;
    2485         }
    2486 
    2487         $supported = imagetypes();
    2488         if( ( $ext == 'jpg' && !($supported & IMG_JPG) ) ||
    2489             ( $ext == 'gif' && !($supported & IMG_GIF) ) ||
    2490             ( $ext == 'png' && !($supported & IMG_PNG) ) ||
    2491             ( $ext == 'bmp' && !($supported & IMG_WBMP) ) ||
    2492             ( $ext == 'xpm' && !($supported & IMG_XPM) ) ) {
    2493 
    2494             JpGraphError::RaiseL(25037,$aFile);//('The image format of your background image ('.$aFile.') is not supported in your system configuration. ');
    2495         }
    2496 
    2497 
    2498         if( $imgtag == "jpg" || $imgtag == "jpeg") {
    2499             $f = "imagecreatefromjpeg";
    2500             $imgtag = "jpg";
    2501         }
    2502         else {
    2503             $f = "imagecreatefrom".$imgtag;
    2504         }
    2505 
    2506         // Compare specified image type and file extension
    2507         if( $imgtag != $ext ) {
    2508             //$t = "Background image seems to be of different type (has different file extension) than specified imagetype. Specified: '".$aImgFormat."'File: '".$aFile."'";
    2509             JpGraphError::RaiseL(25038, $aImgFormat, $aFile);
    2510         }
    2511 
    2512         $img = @$f($aFile);
    2513         if( !$img ) {
    2514             JpGraphError::RaiseL(25039,$aFile);//(" Can't read background image: '".$aFile."'");
    2515         }
    2516         return $img;
    2517     }
    2518 
    2519     function StrokePlotGrad() {
    2520         if( $this->plot_gradtype < 0  )
    2521             return;
    2522            
    2523         $grad = new Gradient($this->img);
    2524         $xl = $this->img->left_margin;
    2525         $yt = $this->img->top_margin;
    2526         $xr = $xl + $this->img->plotwidth+1 ;
    2527         $yb = $yt + $this->img->plotheight ;
    2528         $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->plot_gradfrom,$this->plot_gradto,$this->plot_gradtype);
    2529 
    2530     }
     2225        if( $aImgStr != '' ) {
     2226            return Image::CreateFromString($aImgStr);
     2227        }
     2228
     2229        // Remove case sensitivity and setup appropriate function to create image
     2230        // Get file extension. This should be the LAST '.' separated part of the filename
     2231        $e = explode('.',$aFile);
     2232        $ext = strtolower($e[count($e)-1]);
     2233        if ($ext == "jpeg")  {
     2234            $ext = "jpg";
     2235        }
     2236       
     2237        if( trim($ext) == '' )
     2238            $ext = 'png';  // Assume PNG if no extension specified
     2239
     2240        if( $aImgFormat == '' )
     2241            $imgtag = $ext;
     2242        else
     2243            $imgtag = $aImgFormat;
     2244
     2245        $supported = imagetypes();
     2246        if( ( $ext == 'jpg' && !($supported & IMG_JPG) ) ||
     2247            ( $ext == 'gif' && !($supported & IMG_GIF) ) ||
     2248            ( $ext == 'png' && !($supported & IMG_PNG) ) ||
     2249            ( $ext == 'bmp' && !($supported & IMG_WBMP) ) ||
     2250            ( $ext == 'xpm' && !($supported & IMG_XPM) ) ) {
     2251
     2252            JpGraphError::RaiseL(25037,$aFile);//('The image format of your background image ('.$aFile.') is not supported in your system configuration. ');
     2253        }
     2254
     2255
     2256        if( $imgtag == "jpg" || $imgtag == "jpeg")
     2257        {
     2258            $f = "imagecreatefromjpeg";
     2259            $imgtag = "jpg";
     2260        }
     2261        else
     2262        {
     2263            $f = "imagecreatefrom".$imgtag;
     2264        }
     2265
     2266        // Compare specified image type and file extension
     2267        if( $imgtag != $ext ) {
     2268            //$t = "Background image seems to be of different type (has different file extension) than specified imagetype. Specified: '".$aImgFormat."'File: '".$aFile."'";
     2269            JpGraphError::RaiseL(25038, $aImgFormat, $aFile);
     2270        }
     2271
     2272        $img = @$f($aFile);
     2273        if( !$img ) {
     2274            JpGraphError::RaiseL(25039,$aFile);//(" Can't read background image: '".$aFile."'");   
     2275        }
     2276        return $img;
     2277    }   
    25312278
    25322279    function StrokeBackgroundGrad() {
    2533         if( $this->bkg_gradtype < 0  )
    2534             return;
    2535 
    2536         $grad = new Gradient($this->img);
    2537         if( $this->bkg_gradstyle == BGRAD_PLOT ) {
    2538             $xl = $this->img->left_margin;
    2539             $yt = $this->img->top_margin;
    2540             $xr = $xl + $this->img->plotwidth+1 ;
    2541             $yb = $yt + $this->img->plotheight ;
    2542             $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype);
    2543         }
    2544         else {
    2545             $xl = 0;
    2546             $yt = 0;
    2547             $xr = $xl + $this->img->width - 1;
    2548             $yb = $yt + $this->img->height - 1 ;
    2549             if( $this->doshadow  ) {
    2550                 $xr -= $this->shadow_width;
    2551                 $yb -= $this->shadow_width;
    2552             }
    2553             if( $this->doframe ) {
    2554                 $yt += $this->frame_weight;
    2555                 $yb -= $this->frame_weight;
    2556                 $xl += $this->frame_weight;
    2557                 $xr -= $this->frame_weight;
    2558             }
    2559             $aa = $this->img->SetAngle(0);
    2560             $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype);
    2561             $aa = $this->img->SetAngle($aa);
    2562         }
     2280        if( $this->bkg_gradtype < 0  )
     2281            return;
     2282        $grad = new Gradient($this->img);
     2283        if( $this->bkg_gradstyle == BGRAD_PLOT ) {
     2284            $xl = $this->img->left_margin;
     2285            $yt = $this->img->top_margin;
     2286            $xr = $xl + $this->img->plotwidth+1 ;
     2287            $yb = $yt + $this->img->plotheight ;
     2288            $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype);
     2289        }
     2290        else {
     2291            $xl = 0;
     2292            $yt = 0;
     2293            $xr = $xl + $this->img->width - 1;
     2294            $yb = $yt + $this->img->height ;
     2295            if( $this->doshadow  ) {
     2296                $xr -= $this->shadow_width;
     2297                $yb -= $this->shadow_width;
     2298            }
     2299            if( $this->doframe ) {
     2300                $yt += $this->frame_weight;
     2301                $yb -= $this->frame_weight;   
     2302                $xl += $this->frame_weight;
     2303                $xr -= $this->frame_weight;
     2304            }
     2305            $aa = $this->img->SetAngle(0);
     2306            $grad->FilledRectangle($xl,$yt,$xr,$yb,$this->bkg_gradfrom,$this->bkg_gradto,$this->bkg_gradtype);
     2307            $aa = $this->img->SetAngle($aa);
     2308        }
    25632309    }
    25642310
    25652311    function StrokeFrameBackground() {
    2566         if( $this->background_image != '' && $this->background_cflag != '' ) {
    2567             JpGraphError::RaiseL(25040);//('It is not possible to specify both a background image and a background country flag.');
    2568         }
    2569         if( $this->background_image != '' ) {
    2570             $bkgimg = $this->LoadBkgImage($this->background_image_format,$this->background_image);
    2571         }
    2572         elseif( $this->background_cflag != '' ) {
    2573             if( ! class_exists('FlagImages',false) ) {
    2574                 JpGraphError::RaiseL(25041);//('In order to use Country flags as backgrounds you must include the "jpgraph_flags.php" file.');
    2575             }
    2576             $fobj = new FlagImages(FLAGSIZE4);
    2577             $dummy='';
    2578             $bkgimg = $fobj->GetImgByName($this->background_cflag,$dummy);
    2579             $this->background_image_mix = $this->background_cflag_mix;
    2580             $this->background_image_type = $this->background_cflag_type;
    2581         }
    2582         else {
    2583             return ;
    2584         }
    2585 
    2586         $bw = ImageSX($bkgimg);
    2587         $bh = ImageSY($bkgimg);
    2588 
    2589         // No matter what the angle is we always stroke the image and frame
    2590         // assuming it is 0 degree
    2591         $aa = $this->img->SetAngle(0);
    2592 
    2593         switch( $this->background_image_type ) {
    2594             case BGIMG_FILLPLOT: // Resize to just fill the plotarea
    2595                 $this->FillMarginArea();
    2596                 $this->StrokeFrame();
    2597                 // Special case to hande 90 degree rotated graph corectly
    2598                 if( $aa == 90 ) {
    2599                     $this->img->SetAngle(90);
    2600                     $this->FillPlotArea();
    2601                     $aa = $this->img->SetAngle(0);
    2602                     $adj = ($this->img->height - $this->img->width)/2;
    2603                     $this->img->CopyMerge($bkgimg,
    2604                         $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
    2605                         0,0,
    2606                         $this->img->plotheight+1,$this->img->plotwidth,
    2607                         $bw,$bh,$this->background_image_mix);
    2608                 }
    2609                 else {
    2610                     $this->FillPlotArea();
    2611                     $this->img->CopyMerge($bkgimg,
    2612                         $this->img->left_margin,$this->img->top_margin+1,
    2613                         0,0,$this->img->plotwidth+1,$this->img->plotheight,
    2614                         $bw,$bh,$this->background_image_mix);
    2615                 }
    2616                 break;
    2617             case BGIMG_FILLFRAME: // Fill the whole area from upper left corner, resize to just fit
    2618                 $hadj=0; $vadj=0;
    2619                 if( $this->doshadow ) {
    2620                     $hadj = $this->shadow_width;
    2621                     $vadj = $this->shadow_width;
    2622                 }
    2623                 $this->FillMarginArea();
    2624                 $this->FillPlotArea();
    2625                 $this->img->CopyMerge($bkgimg,0,0,0,0,$this->img->width-$hadj,$this->img->height-$vadj,
    2626                 $bw,$bh,$this->background_image_mix);
    2627                 $this->StrokeFrame();
    2628                 break;
    2629             case BGIMG_COPY: // Just copy the image from left corner, no resizing
    2630                 $this->FillMarginArea();
    2631                 $this->FillPlotArea();
    2632                 $this->img->CopyMerge($bkgimg,0,0,0,0,$bw,$bh,
    2633                 $bw,$bh,$this->background_image_mix);
    2634                 $this->StrokeFrame();
    2635                 break;
    2636             case BGIMG_CENTER: // Center original image in the plot area
    2637                 $this->FillMarginArea();
    2638                 $this->FillPlotArea();
    2639                 $centerx = round($this->img->plotwidth/2+$this->img->left_margin-$bw/2);
    2640                 $centery = round($this->img->plotheight/2+$this->img->top_margin-$bh/2);
    2641                 $this->img->CopyMerge($bkgimg,$centerx,$centery,0,0,$bw,$bh,
    2642                 $bw,$bh,$this->background_image_mix);
    2643                 $this->StrokeFrame();
    2644                 break;
    2645             case BGIMG_FREE: // Just copy the image to the specified location
    2646                 $this->img->CopyMerge($bkgimg,
    2647                 $this->background_image_xpos,$this->background_image_ypos,
    2648                 0,0,$bw,$bh,$bw,$bh,$this->background_image_mix);
    2649                 $this->StrokeFrame(); // New
    2650                 break;
    2651             default:
    2652                 JpGraphError::RaiseL(25042);//(" Unknown background image layout");
    2653         }
    2654         $this->img->SetAngle($aa);
     2312        if( $this->background_image != "" && $this->background_cflag != "" ) {
     2313            JpGraphError::RaiseL(25040);//('It is not possible to specify both a background image and a background country flag.');
     2314        }
     2315        if( $this->background_image != "" ) {
     2316            $bkgimg = $this->LoadBkgImage($this->background_image_format,$this->background_image);
     2317        }
     2318        elseif( $this->background_cflag != "" ) {
     2319            if( ! class_exists('FlagImages',false) ) {
     2320                JpGraphError::RaiseL(25041);//('In order to use Country flags as backgrounds you must include the "jpgraph_flags.php" file.');
     2321            }
     2322            $fobj = new FlagImages(FLAGSIZE4);
     2323            $dummy='';
     2324            $bkgimg = $fobj->GetImgByName($this->background_cflag,$dummy);
     2325            $this->background_image_mix = $this->background_cflag_mix;
     2326            $this->background_image_type = $this->background_cflag_type;
     2327        }
     2328        else {
     2329            return ;
     2330        }
     2331
     2332        $bw = ImageSX($bkgimg);
     2333        $bh = ImageSY($bkgimg);
     2334
     2335        // No matter what the angle is we always stroke the image and frame
     2336        // assuming it is 0 degree
     2337        $aa = $this->img->SetAngle(0);
     2338               
     2339        switch( $this->background_image_type ) {
     2340            case BGIMG_FILLPLOT: // Resize to just fill the plotarea
     2341                $this->FillMarginArea();
     2342                $this->StrokeFrame();
     2343                // Special case to hande 90 degree rotated graph corectly
     2344                if( $aa == 90 ) {
     2345                    $this->img->SetAngle(90);
     2346                    $this->FillPlotArea();
     2347                    $aa = $this->img->SetAngle(0);
     2348                    $adj = ($this->img->height - $this->img->width)/2;
     2349                    $this->img->CopyMerge($bkgimg,
     2350                                          $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
     2351                                          0,0,
     2352                                          $this->img->plotheight+1,$this->img->plotwidth,
     2353                                          $bw,$bh,$this->background_image_mix);
     2354
     2355                }
     2356                else {
     2357                    $this->FillPlotArea();
     2358                    $this->img->CopyMerge($bkgimg,
     2359                                          $this->img->left_margin,$this->img->top_margin,
     2360                                          0,0,$this->img->plotwidth+1,$this->img->plotheight,
     2361                                          $bw,$bh,$this->background_image_mix);
     2362                }
     2363                break;
     2364            case BGIMG_FILLFRAME: // Fill the whole area from upper left corner, resize to just fit
     2365                $hadj=0; $vadj=0;
     2366                if( $this->doshadow ) {
     2367                    $hadj = $this->shadow_width;
     2368                    $vadj = $this->shadow_width;
     2369                }
     2370                $this->FillMarginArea();
     2371                $this->FillPlotArea();
     2372                $this->img->CopyMerge($bkgimg,0,0,0,0,$this->img->width-$hadj,$this->img->height-$vadj,
     2373                                      $bw,$bh,$this->background_image_mix);
     2374                $this->StrokeFrame();
     2375                break;
     2376            case BGIMG_COPY: // Just copy the image from left corner, no resizing
     2377                $this->FillMarginArea();
     2378                $this->FillPlotArea();
     2379                $this->img->CopyMerge($bkgimg,0,0,0,0,$bw,$bh,
     2380                                      $bw,$bh,$this->background_image_mix);
     2381                $this->StrokeFrame();
     2382                break;
     2383            case BGIMG_CENTER: // Center original image in the plot area
     2384                $this->FillMarginArea();
     2385                $this->FillPlotArea();
     2386                $centerx = round($this->img->plotwidth/2+$this->img->left_margin-$bw/2);
     2387                $centery = round($this->img->plotheight/2+$this->img->top_margin-$bh/2);
     2388                $this->img->CopyMerge($bkgimg,$centerx,$centery,0,0,$bw,$bh,
     2389                                      $bw,$bh,$this->background_image_mix);
     2390                $this->StrokeFrame();
     2391                break;
     2392            case BGIMG_FREE: // Just copy the image to the specified location
     2393                $this->img->CopyMerge($bkgimg,
     2394                                      $this->background_image_xpos,$this->background_image_ypos,
     2395                                      0,0,$bw,$bh,$bw,$bh,$this->background_image_mix);
     2396                $this->StrokeFrame(); // New
     2397                break;
     2398            default:
     2399                JpGraphError::RaiseL(25042);//(" Unknown background image layout");
     2400        }                       
     2401        $this->img->SetAngle($aa);             
    26552402    }
    26562403
     
    26582405    // Draw a frame around the image
    26592406    function StrokeFrame() {
    2660         if( !$this->doframe ) return;
    2661 
    2662         if( $this->background_image_type <= 1 && ($this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_PLOT)) ) {
    2663             $c = $this->margin_color;
    2664         }
    2665         else {
    2666             $c = false;
    2667         }
    2668 
    2669         if( $this->doshadow ) {
    2670             $this->img->SetColor($this->frame_color);
    2671             $this->img->ShadowRectangle(0,0,$this->img->width,$this->img->height,
    2672             $c,$this->shadow_width,$this->shadow_color);
    2673         }
    2674         elseif( $this->framebevel ) {
    2675             if( $c ) {
    2676                 $this->img->SetColor($this->margin_color);
    2677                 $this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1);
    2678             }
    2679             $this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2,
    2680             $this->framebeveldepth,
    2681             $this->framebevelcolor1,$this->framebevelcolor2);
    2682             if( $this->framebevelborder ) {
    2683                 $this->img->SetColor($this->framebevelbordercolor);
    2684                 $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1);
    2685             }
    2686         }
    2687         else {
    2688             $this->img->SetLineWeight($this->frame_weight);
    2689             if( $c ) {
    2690                 $this->img->SetColor($this->margin_color);
    2691                 $this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1);
    2692             }
    2693             $this->img->SetColor($this->frame_color);
    2694             $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1);
    2695         }
     2407        if( !$this->doframe ) return;
     2408
     2409        if( $this->background_image_type <= 1 &&
     2410            ($this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_PLOT)) ) {
     2411            $c = $this->margin_color;
     2412        }
     2413        else {
     2414            $c = false;
     2415        }
     2416       
     2417        if( $this->doshadow ) {
     2418            $this->img->SetColor($this->frame_color);                   
     2419            $this->img->ShadowRectangle(0,0,$this->img->width,$this->img->height,
     2420                                        $c,$this->shadow_width,$this->shadow_color);
     2421        }
     2422        elseif( $this->framebevel ) {
     2423            if( $c ) {
     2424                $this->img->SetColor($this->margin_color);
     2425                $this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1);
     2426            }
     2427            $this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2,
     2428                              $this->framebeveldepth,
     2429                              $this->framebevelcolor1,$this->framebevelcolor2);
     2430            if( $this->framebevelborder ) {
     2431                $this->img->SetColor($this->framebevelbordercolor);
     2432                $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1);
     2433            }
     2434        }
     2435        else {
     2436            $this->img->SetLineWeight($this->frame_weight);
     2437            if( $c ) {
     2438                $this->img->SetColor($this->margin_color);
     2439                $this->img->FilledRectangle(0,0,$this->img->width-1,$this->img->height-1);
     2440            }
     2441            $this->img->SetColor($this->frame_color);
     2442            $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1);               
     2443        }
    26962444    }
    26972445
    26982446    function FillMarginArea() {
    2699         $hadj=0; $vadj=0;
    2700         if( $this->doshadow ) {
    2701             $hadj = $this->shadow_width;
    2702             $vadj = $this->shadow_width;
    2703         }
    2704 
    2705         $this->img->SetColor($this->margin_color);
    2706         $this->img->FilledRectangle(0,0,$this->img->width-1-$hadj,$this->img->height-1-$vadj);
    2707 
    2708         $this->img->FilledRectangle(0,0,$this->img->width-1-$hadj,$this->img->top_margin);
    2709         $this->img->FilledRectangle(0,$this->img->top_margin,$this->img->left_margin,$this->img->height-1-$hadj);
    2710         $this->img->FilledRectangle($this->img->left_margin+1,
    2711         $this->img->height-$this->img->bottom_margin,
    2712         $this->img->width-1-$hadj,
    2713         $this->img->height-1-$hadj);
    2714         $this->img->FilledRectangle($this->img->width-$this->img->right_margin,
    2715         $this->img->top_margin+1,
    2716         $this->img->width-1-$hadj,
    2717         $this->img->height-$this->img->bottom_margin-1);
     2447        $hadj=0; $vadj=0;
     2448        if( $this->doshadow ) {
     2449            $hadj = $this->shadow_width;
     2450            $vadj = $this->shadow_width;
     2451        }
     2452
     2453        $this->img->SetColor($this->margin_color);
     2454//      $this->img->FilledRectangle(0,0,$this->img->width-1-$hadj,$this->img->height-1-$vadj);
     2455
     2456        $this->img->FilledRectangle(0,0,$this->img->width-1-$hadj,$this->img->top_margin);
     2457        $this->img->FilledRectangle(0,$this->img->top_margin,$this->img->left_margin,$this->img->height-1-$hadj);
     2458        $this->img->FilledRectangle($this->img->left_margin+1,
     2459                                    $this->img->height-$this->img->bottom_margin,
     2460                                    $this->img->width-1-$hadj,
     2461                                    $this->img->height-1-$hadj);
     2462        $this->img->FilledRectangle($this->img->width-$this->img->right_margin,
     2463                                    $this->img->top_margin+1,
     2464                                    $this->img->width-1-$hadj,
     2465                                    $this->img->height-$this->img->bottom_margin-1);
    27182466    }
    27192467
    27202468    function FillPlotArea() {
    2721         $this->img->PushColor($this->plotarea_color);
    2722         $this->img->FilledRectangle($this->img->left_margin,
    2723         $this->img->top_margin,
    2724         $this->img->width-$this->img->right_margin,
    2725         $this->img->height-$this->img->bottom_margin);
    2726         $this->img->PopColor();
    2727     }
    2728 
     2469        $this->img->PushColor($this->plotarea_color);
     2470        $this->img->FilledRectangle($this->img->left_margin,
     2471                                    $this->img->top_margin,
     2472                                    $this->img->width-$this->img->right_margin,
     2473                                    $this->img->height-$this->img->bottom_margin);     
     2474        $this->img->PopColor();
     2475    }
     2476   
    27292477    // Stroke the plot area with either a solid color or a background image
    27302478    function StrokePlotArea() {
    2731         // Note: To be consistent we really should take a possible shadow
    2732         // into account. However, that causes some problem for the LinearScale class
    2733         // since in the current design it does not have any links to class Graph which
    2734         // means it has no way of compensating for the adjusted plotarea in case of a
    2735         // shadow. So, until I redesign LinearScale we can't compensate for this.
    2736         // So just set the two adjustment parameters to zero for now.
    2737         $boxadj = 0; //$this->doframe ? $this->frame_weight : 0 ;
    2738         $adj = 0; //$this->doshadow ? $this->shadow_width : 0 ;
    2739 
    2740         if( $this->background_image != '' || $this->background_cflag != '' ) {
    2741             $this->StrokeFrameBackground();
    2742         }
    2743         else {
    2744             $aa = $this->img->SetAngle(0);
    2745             $this->StrokeFrame();
    2746             $aa = $this->img->SetAngle($aa);
    2747             $this->StrokeBackgroundGrad();
    2748             if( $this->bkg_gradtype < 0 || ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_MARGIN) ) {
    2749                 $this->FillPlotArea();
    2750             }
    2751             $this->StrokePlotGrad();
    2752         }
    2753     }
     2479        // Note: To be consistent we really should take a possible shadow
     2480        // into account. However, that causes some problem for the LinearScale class
     2481        // since in the current design it does not have any links to class Graph which
     2482        // means it has no way of compensating for the adjusted plotarea in case of a
     2483        // shadow. So, until I redesign LinearScale we can't compensate for this.
     2484        // So just set the two adjustment parameters to zero for now.
     2485        $boxadj = 0; //$this->doframe ? $this->frame_weight : 0 ;
     2486        $adj = 0; //$this->doshadow ? $this->shadow_width : 0 ;
     2487
     2488        if( $this->background_image != "" || $this->background_cflag != "" ) {
     2489            $this->StrokeFrameBackground();
     2490        }
     2491        else {
     2492            $aa = $this->img->SetAngle(0);
     2493            $this->StrokeFrame();
     2494            $aa = $this->img->SetAngle($aa);
     2495            $this->StrokeBackgroundGrad();
     2496            if( $this->bkg_gradtype < 0 ||
     2497                ($this->bkg_gradtype > 0 && $this->bkg_gradstyle==BGRAD_MARGIN) ) {
     2498                $this->FillPlotArea();
     2499            }
     2500        }       
     2501    }   
    27542502
    27552503    function StrokeIcons() {
    2756         $n = count($this->iIcons);
    2757         for( $i=0; $i < $n; ++$i ) {
    2758             $this->iIcons[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale);
    2759         }
    2760     }
    2761 
     2504        $n = count($this->iIcons);
     2505        for( $i=0; $i < $n; ++$i ) {
     2506            $this->iIcons[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale);
     2507        }
     2508    }
     2509       
    27622510    function StrokePlotBox() {
    2763         // Should we draw a box around the plot area?
    2764         if( $this->boxed ) {
    2765             $this->img->SetLineWeight(1);
    2766             $this->img->SetLineStyle('solid');
    2767             $this->img->SetColor($this->box_color);
    2768             for($i=0; $i < $this->box_weight; ++$i ) {
    2769                 $this->img->Rectangle(
    2770                 $this->img->left_margin-$i,$this->img->top_margin-$i,
    2771                 $this->img->width-$this->img->right_margin+$i,
    2772                 $this->img->height-$this->img->bottom_margin+$i);
    2773             }
    2774         }
    2775     }
     2511        // Should we draw a box around the plot area?
     2512        if( $this->boxed ) {
     2513            $this->img->SetLineWeight(1);
     2514            $this->img->SetLineStyle('solid');
     2515            $this->img->SetColor($this->box_color);
     2516            for($i=0; $i < $this->box_weight; ++$i ) {
     2517                $this->img->Rectangle(
     2518                    $this->img->left_margin-$i,$this->img->top_margin-$i,
     2519                    $this->img->width-$this->img->right_margin+$i,
     2520                    $this->img->height-$this->img->bottom_margin+$i);
     2521            }
     2522        }                                               
     2523    }           
    27762524
    27772525    function SetTitleBackgroundFillStyle($aStyle,$aColor1='black',$aColor2='white') {
    2778         $this->titlebkg_fillstyle = $aStyle;
    2779         $this->titlebkg_scolor1 = $aColor1;
    2780         $this->titlebkg_scolor2 = $aColor2;
     2526        $this->titlebkg_fillstyle = $aStyle;
     2527        $this->titlebkg_scolor1 = $aColor1;
     2528        $this->titlebkg_scolor2 = $aColor2;
    27812529    }
    27822530
    27832531    function SetTitleBackground($aBackColor='gray', $aStyle=TITLEBKG_STYLE1, $aFrameStyle=TITLEBKG_FRAME_NONE, $aFrameColor='black', $aFrameWeight=1, $aBevelHeight=3, $aEnable=true) {
    2784         $this->titlebackground = $aEnable;
    2785         $this->titlebackground_color = $aBackColor;
    2786         $this->titlebackground_style = $aStyle;
    2787         $this->titlebackground_framecolor = $aFrameColor;
    2788         $this->titlebackground_framestyle = $aFrameStyle;
    2789         $this->titlebackground_frameweight = $aFrameWeight;
    2790         $this->titlebackground_bevelheight = $aBevelHeight ;
     2532        $this->titlebackground = $aEnable;
     2533        $this->titlebackground_color = $aBackColor;
     2534        $this->titlebackground_style = $aStyle;
     2535        $this->titlebackground_framecolor = $aFrameColor;
     2536        $this->titlebackground_framestyle = $aFrameStyle;
     2537        $this->titlebackground_frameweight = $aFrameWeight;     
     2538        $this->titlebackground_bevelheight = $aBevelHeight ;
    27912539    }
    27922540
     
    27942542    function StrokeTitles() {
    27952543
    2796         $margin=3;
    2797 
    2798         if( $this->titlebackground ) {
    2799             // Find out height
    2800             $this->title->margin += 2 ;
    2801             $h = $this->title->GetTextHeight($this->img)+$this->title->margin+$margin;
    2802             if( $this->subtitle->t != '' && !$this->subtitle->hide ) {
    2803                 $h += $this->subtitle->GetTextHeight($this->img)+$margin+
    2804                 $this->subtitle->margin;
    2805                 $h += 2;
    2806             }
    2807             if( $this->subsubtitle->t != '' && !$this->subsubtitle->hide ) {
    2808                 $h += $this->subsubtitle->GetTextHeight($this->img)+$margin+
    2809                 $this->subsubtitle->margin;
    2810                 $h += 2;
    2811             }
    2812             $this->img->PushColor($this->titlebackground_color);
    2813             if( $this->titlebackground_style === TITLEBKG_STYLE1 ) {
    2814                 // Inside the frame
    2815                 if( $this->framebevel ) {
    2816                     $x1 = $y1 = $this->framebeveldepth + 1 ;
    2817                     $x2 = $this->img->width - $this->framebeveldepth - 2 ;
    2818                     $this->title->margin += $this->framebeveldepth + 1 ;
    2819                     $h += $y1 ;
    2820                     $h += 2;
    2821                 }
    2822                 else {
    2823                     $x1 = $y1 = $this->frame_weight;
    2824                     $x2 = $this->img->width - $this->frame_weight-1;
    2825                 }
    2826             }
    2827             elseif( $this->titlebackground_style === TITLEBKG_STYLE2 ) {
    2828                 // Cover the frame as well
    2829                 $x1 = $y1 = 0;
    2830                 $x2 = $this->img->width - 1 ;
    2831             }
    2832             elseif( $this->titlebackground_style === TITLEBKG_STYLE3 ) {
    2833                 // Cover the frame as well (the difference is that
    2834                 // for style==3 a bevel frame border is on top
    2835                 // of the title background)
    2836                 $x1 = $y1 = 0;
    2837                 $x2 = $this->img->width - 1 ;
    2838                 $h += $this->framebeveldepth ;
    2839                 $this->title->margin += $this->framebeveldepth ;
    2840             }
    2841             else {
    2842                 JpGraphError::RaiseL(25043);//('Unknown title background style.');
    2843             }
    2844 
    2845             if( $this->titlebackground_framestyle === 3 ) {
    2846                 $h += $this->titlebackground_bevelheight*2 + 1  ;
    2847                 $this->title->margin += $this->titlebackground_bevelheight ;
    2848             }
    2849 
    2850             if( $this->doshadow ) {
    2851                 $x2 -= $this->shadow_width ;
    2852             }
    2853 
    2854             $indent=0;
    2855             if( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) {
    2856                 $indent = $this->titlebackground_bevelheight;
    2857             }
    2858 
    2859             if( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_HSTRIPED ) {
    2860                 $this->img->FilledRectangle2($x1+$indent,$y1+$indent,$x2-$indent,$h-$indent,
    2861                 $this->titlebkg_scolor1,
    2862                 $this->titlebkg_scolor2);
    2863             }
    2864             elseif( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_VSTRIPED ) {
    2865                 $this->img->FilledRectangle2($x1+$indent,$y1+$indent,$x2-$indent,$h-$indent,
    2866                 $this->titlebkg_scolor1,
    2867                 $this->titlebkg_scolor2,2);
    2868             }
    2869             else {
    2870                 // Solid fill
    2871                 $this->img->FilledRectangle($x1,$y1,$x2,$h);
    2872             }
    2873             $this->img->PopColor();
    2874 
    2875             $this->img->PushColor($this->titlebackground_framecolor);
    2876             $this->img->SetLineWeight($this->titlebackground_frameweight);
    2877             if( $this->titlebackground_framestyle == TITLEBKG_FRAME_FULL ) {
    2878                 // Frame background
    2879                 $this->img->Rectangle($x1,$y1,$x2,$h);
    2880             }
    2881             elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BOTTOM ) {
    2882                 // Bottom line only
    2883                 $this->img->Line($x1,$h,$x2,$h);
    2884             }
    2885             elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) {
    2886                 $this->img->Bevel($x1,$y1,$x2,$h,$this->titlebackground_bevelheight);
    2887             }
    2888             $this->img->PopColor();
    2889 
    2890             // This is clumsy. But we neeed to stroke the whole graph frame if it is
    2891             // set to bevel to get the bevel shading on top of the text background
    2892             if( $this->framebevel && $this->doframe && $this->titlebackground_style === 3 ) {
    2893                 $this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2,
    2894                 $this->framebeveldepth,
    2895                 $this->framebevelcolor1,$this->framebevelcolor2);
    2896                 if( $this->framebevelborder ) {
    2897                     $this->img->SetColor($this->framebevelbordercolor);
    2898                     $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1);
    2899                 }
    2900             }
    2901         }
    2902 
    2903         // Stroke title
    2904         $y = $this->title->margin;
    2905         if( $this->title->halign == 'center' ) {
    2906             $this->title->Center(0,$this->img->width,$y);
    2907         }
    2908         elseif( $this->title->halign == 'left' ) {
    2909             $this->title->SetPos($this->title->margin+2,$y);
    2910         }
    2911         elseif( $this->title->halign == 'right' ) {
    2912             $indent = 0;
    2913             if( $this->doshadow ) {
    2914                 $indent = $this->shadow_width+2;
    2915             }
    2916             $this->title->SetPos($this->img->width-$this->title->margin-$indent,$y,'right');
    2917         }
    2918         $this->title->Stroke($this->img);
    2919 
    2920         // ... and subtitle
    2921         $y += $this->title->GetTextHeight($this->img) + $margin + $this->subtitle->margin;
    2922         if( $this->subtitle->halign == 'center' ) {
    2923             $this->subtitle->Center(0,$this->img->width,$y);
    2924         }
    2925         elseif( $this->subtitle->halign == 'left' ) {
    2926             $this->subtitle->SetPos($this->subtitle->margin+2,$y);
    2927         }
    2928         elseif( $this->subtitle->halign == 'right' ) {
    2929             $indent = 0;
    2930             if( $this->doshadow )
    2931             $indent = $this->shadow_width+2;
    2932             $this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right');
    2933         }
    2934         $this->subtitle->Stroke($this->img);
    2935 
    2936         // ... and subsubtitle
    2937         $y += $this->subtitle->GetTextHeight($this->img) + $margin + $this->subsubtitle->margin;
    2938         if( $this->subsubtitle->halign == 'center' ) {
    2939             $this->subsubtitle->Center(0,$this->img->width,$y);
    2940         }
    2941         elseif( $this->subsubtitle->halign == 'left' ) {
    2942             $this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y);
    2943         }
    2944         elseif( $this->subsubtitle->halign == 'right' ) {
    2945             $indent = 0;
    2946             if( $this->doshadow )
    2947             $indent = $this->shadow_width+2;
    2948             $this->subsubtitle->SetPos($this->img->width-$this->subsubtitle->margin-$indent,$y,'right');
    2949         }
    2950         $this->subsubtitle->Stroke($this->img);
    2951 
    2952         // ... and fancy title
    2953         $this->tabtitle->Stroke($this->img);
     2544        $margin=3;
     2545
     2546        if( $this->titlebackground ) {
     2547
     2548            // Find out height
     2549            $this->title->margin += 2 ;
     2550            $h = $this->title->GetTextHeight($this->img)+$this->title->margin+$margin;
     2551            if( $this->subtitle->t != "" && !$this->subtitle->hide ) {
     2552                $h += $this->subtitle->GetTextHeight($this->img)+$margin+
     2553                    $this->subtitle->margin;
     2554                $h += 2;
     2555            }
     2556            if( $this->subsubtitle->t != "" && !$this->subsubtitle->hide ) {
     2557                $h += $this->subsubtitle->GetTextHeight($this->img)+$margin+
     2558                    $this->subsubtitle->margin;
     2559                $h += 2;
     2560            }
     2561            $this->img->PushColor($this->titlebackground_color);
     2562            if( $this->titlebackground_style === TITLEBKG_STYLE1 ) {
     2563                // Inside the frame
     2564                if( $this->framebevel ) {
     2565                    $x1 = $y1 = $this->framebeveldepth + 1 ;
     2566                    $x2 = $this->img->width - $this->framebeveldepth - 2 ;
     2567                    $this->title->margin += $this->framebeveldepth + 1 ;
     2568                    $h += $y1 ;
     2569                    $h += 2;
     2570                }
     2571                else {
     2572                    $x1 = $y1 = $this->frame_weight;
     2573                    $x2 = $this->img->width - 2*$x1;
     2574                }
     2575            }
     2576            elseif( $this->titlebackground_style === TITLEBKG_STYLE2 ) {
     2577                // Cover the frame as well
     2578                $x1 = $y1 = 0;
     2579                $x2 = $this->img->width - 1 ;
     2580            }
     2581            elseif( $this->titlebackground_style === TITLEBKG_STYLE3 ) {
     2582                // Cover the frame as well (the difference is that
     2583                // for style==3 a bevel frame border is on top
     2584                // of the title background)
     2585                $x1 = $y1 = 0;
     2586                $x2 = $this->img->width - 1 ;
     2587                $h += $this->framebeveldepth ;
     2588                $this->title->margin += $this->framebeveldepth ;
     2589            }
     2590            else {
     2591                JpGraphError::RaiseL(25043);//('Unknown title background style.');
     2592            }
     2593
     2594            if( $this->titlebackground_framestyle === 3 ) {
     2595                $h += $this->titlebackground_bevelheight*2 + 1  ;
     2596                $this->title->margin += $this->titlebackground_bevelheight ;
     2597            }
     2598
     2599            if( $this->doshadow ) {
     2600                $x2 -= $this->shadow_width ;
     2601            }
     2602           
     2603            $indent=0;
     2604            if( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) {
     2605                $ind = $this->titlebackground_bevelheight;
     2606            }
     2607
     2608            if( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_HSTRIPED ) {
     2609                $this->img->FilledRectangle2($x1+$ind,$y1+$ind,$x2-$ind,$h-$ind,
     2610                                             $this->titlebkg_scolor1,
     2611                                             $this->titlebkg_scolor2);
     2612            }
     2613            elseif( $this->titlebkg_fillstyle==TITLEBKG_FILLSTYLE_VSTRIPED ) {
     2614                $this->img->FilledRectangle2($x1+$ind,$y1+$ind,$x2-$ind,$h-$ind,
     2615                                             $this->titlebkg_scolor1,
     2616                                             $this->titlebkg_scolor2,2);
     2617            }
     2618            else {
     2619                // Solid fill
     2620                $this->img->FilledRectangle($x1,$y1,$x2,$h);
     2621            }
     2622            $this->img->PopColor();
     2623
     2624            $this->img->PushColor($this->titlebackground_framecolor);
     2625            $this->img->SetLineWeight($this->titlebackground_frameweight);
     2626            if( $this->titlebackground_framestyle == TITLEBKG_FRAME_FULL ) {
     2627                // Frame background
     2628                $this->img->Rectangle($x1,$y1,$x2,$h);
     2629            }
     2630            elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BOTTOM ) {
     2631                // Bottom line only
     2632                $this->img->Line($x1,$h,$x2,$h);
     2633            }
     2634            elseif( $this->titlebackground_framestyle == TITLEBKG_FRAME_BEVEL ) {
     2635                $this->img->Bevel($x1,$y1,$x2,$h,$this->titlebackground_bevelheight);
     2636            }
     2637            $this->img->PopColor();
     2638
     2639            // This is clumsy. But we neeed to stroke the whole graph frame if it is
     2640            // set to bevel to get the bevel shading on top of the text background
     2641            if( $this->framebevel && $this->doframe &&
     2642                $this->titlebackground_style === 3 ) {
     2643                $this->img->Bevel(1,1,$this->img->width-2,$this->img->height-2,
     2644                                  $this->framebeveldepth,
     2645                                  $this->framebevelcolor1,$this->framebevelcolor2);
     2646                if( $this->framebevelborder ) {
     2647                    $this->img->SetColor($this->framebevelbordercolor);
     2648                    $this->img->Rectangle(0,0,$this->img->width-1,$this->img->height-1);
     2649                }
     2650            }
     2651        }
     2652
     2653        // Stroke title
     2654        $y = $this->title->margin;
     2655        if( $this->title->halign == 'center' )
     2656            $this->title->Center(0,$this->img->width,$y);
     2657        elseif( $this->title->halign == 'left' ) {
     2658            $this->title->SetPos($this->title->margin+2,$y);
     2659        }
     2660        elseif( $this->title->halign == 'right' ) {
     2661            $indent = 0;
     2662            if( $this->doshadow )
     2663                $indent = $this->shadow_width+2;
     2664            $this->title->SetPos($this->img->width-$this->title->margin-$indent,$y,'right');       
     2665        }
     2666        $this->title->Stroke($this->img);
     2667               
     2668        // ... and subtitle
     2669        $y += $this->title->GetTextHeight($this->img) + $margin + $this->subtitle->margin;
     2670        if( $this->subtitle->halign == 'center' )
     2671            $this->subtitle->Center(0,$this->img->width,$y);
     2672        elseif( $this->subtitle->halign == 'left' ) {
     2673            $this->subtitle->SetPos($this->subtitle->margin+2,$y);
     2674        }
     2675        elseif( $this->subtitle->halign == 'right' ) {
     2676            $indent = 0;
     2677            if( $this->doshadow )
     2678                $indent = $this->shadow_width+2;
     2679            $this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right');
     2680        }
     2681        $this->subtitle->Stroke($this->img);
     2682
     2683        // ... and subsubtitle
     2684        $y += $this->subtitle->GetTextHeight($this->img) + $margin + $this->subsubtitle->margin;
     2685        if( $this->subsubtitle->halign == 'center' )
     2686            $this->subsubtitle->Center(0,$this->img->width,$y);
     2687        elseif( $this->subsubtitle->halign == 'left' ) {
     2688            $this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y);
     2689        }
     2690        elseif( $this->subsubtitle->halign == 'right' ) {
     2691            $indent = 0;
     2692            if( $this->doshadow )
     2693                $indent = $this->shadow_width+2;
     2694            $this->subsubtitle->SetPos($this->img->width-$this->subsubtitle->margin-$indent,$y,'right');
     2695        }
     2696        $this->subsubtitle->Stroke($this->img);
     2697
     2698        // ... and fancy title
     2699        $this->tabtitle->Stroke($this->img);
    29542700
    29552701    }
    29562702
    29572703    function StrokeTexts() {
    2958         // Stroke any user added text objects
    2959         if( $this->texts != null ) {
    2960             for($i=0; $i < count($this->texts); ++$i) {
    2961                 $this->texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale);
    2962             }
    2963         }
    2964 
    2965         if( $this->y2texts != null && $this->y2scale != null ) {
    2966             for($i=0; $i < count($this->y2texts); ++$i) {
    2967                 $this->y2texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->y2scale);
    2968             }
    2969         }
     2704        // Stroke any user added text objects
     2705        if( $this->texts != null ) {
     2706            for($i=0; $i < count($this->texts); ++$i) {
     2707                $this->texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale);
     2708            }
     2709        }
     2710
     2711        if( $this->y2texts != null && $this->y2scale != null ) {
     2712            for($i=0; $i < count($this->y2texts); ++$i) {
     2713                $this->y2texts[$i]->StrokeWithScale($this->img,$this->xscale,$this->y2scale);
     2714            }
     2715        }
    29702716
    29712717    }
    29722718
    29732719    function StrokeTables() {
    2974         if( $this->iTables != null ) {
    2975             $n = count($this->iTables);
    2976             for( $i=0; $i < $n; ++$i ) {
    2977                 $this->iTables[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale);
    2978             }
    2979         }
     2720        if( $this->iTables != null ) {
     2721            $n = count($this->iTables);
     2722            for( $i=0; $i < $n; ++$i ) {
     2723                $this->iTables[$i]->StrokeWithScale($this->img,$this->xscale,$this->yscale);
     2724            }
     2725        }
    29802726    }
    29812727
    29822728    function DisplayClientSideaImageMapAreas() {
    2983         // Debug stuff - display the outline of the image map areas
    2984         $csim='';
    2985         foreach ($this->plots as $p) {
    2986             $csim.= $p->GetCSIMareas();
    2987         }
    2988         $csim .= $this->legend->GetCSIMareas();
    2989         if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) {
    2990             $this->img->SetColor($this->csimcolor);
    2991             $n = count($coords[0]);
    2992             for ($i=0; $i < $n; $i++) {
    2993                 if ( $coords[1][$i] == 'poly' ) {
    2994                     preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts);
    2995                     $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]);
    2996                     $m = count($pts[0]);
    2997                     for ($j=0; $j < $m; $j++) {
    2998                         $this->img->LineTo($pts[1][$j],$pts[2][$j]);
    2999                     }
    3000                 } elseif ( $coords[1][$i] == 'rect' ) {
    3001                     $pts = preg_split('/,/', $coords[2][$i]);
    3002                     $this->img->SetStartPoint($pts[0],$pts[1]);
    3003                     $this->img->LineTo($pts[2],$pts[1]);
    3004                     $this->img->LineTo($pts[2],$pts[3]);
    3005                     $this->img->LineTo($pts[0],$pts[3]);
    3006                     $this->img->LineTo($pts[0],$pts[1]);
    3007                 }
    3008             }
    3009         }
     2729        // Debug stuff - display the outline of the image map areas
     2730        $csim='';
     2731        foreach ($this->plots as $p) {
     2732            $csim.= $p->GetCSIMareas();
     2733        }
     2734        $csim .= $this->legend->GetCSIMareas();
     2735        if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) {
     2736            $this->img->SetColor($this->csimcolor);
     2737            $n = count($coords[0]);
     2738            for ($i=0; $i < $n; $i++) {
     2739                if ($coords[1][$i]=="poly") {
     2740                    preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts);
     2741                    $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]);
     2742                    $m = count($pts[0]);
     2743                    for ($j=0; $j < $m; $j++) {
     2744                        $this->img->LineTo($pts[1][$j],$pts[2][$j]);
     2745                    }
     2746                } else if ($coords[1][$i]=="rect") {
     2747                    $pts = preg_split('/,/', $coords[2][$i]);
     2748                    $this->img->SetStartPoint($pts[0],$pts[1]);
     2749                    $this->img->LineTo($pts[2],$pts[1]);
     2750                    $this->img->LineTo($pts[2],$pts[3]);
     2751                    $this->img->LineTo($pts[0],$pts[3]);
     2752                    $this->img->LineTo($pts[0],$pts[1]);                                       
     2753                }
     2754            }
     2755        }
    30102756    }
    30112757
    30122758    // Text scale offset in world coordinates
    30132759    function SetTextScaleOff($aOff) {
    3014         $this->text_scale_off = $aOff;
    3015         $this->xscale->text_scale_off = $aOff;
     2760        $this->text_scale_off = $aOff;
     2761        $this->xscale->text_scale_off = $aOff;
    30162762    }
    30172763
    30182764    // Text width of bar to be centered in absolute pixels
    30192765    function SetTextScaleAbsCenterOff($aOff) {
    3020         $this->text_scale_abscenteroff = $aOff;
     2766        $this->text_scale_abscenteroff = $aOff;
    30212767    }
    30222768
    30232769    // Get Y min and max values for added lines
    30242770    function GetLinesYMinMax( $aLines ) {
    3025         $n = is_array($aLines) ? count($aLines) : 0;
    3026         if( $n == 0 ) return false;
    3027         $min = $aLines[0]->scaleposition ;
    3028         $max = $min ;
    3029         $flg = false;
    3030         for( $i=0; $i < $n; ++$i ) {
    3031             if( $aLines[$i]->direction == HORIZONTAL ) {
    3032                 $flg = true ;
    3033                 $v = $aLines[$i]->scaleposition ;
    3034                 if( $min > $v ) $min = $v ;
    3035                 if( $max < $v ) $max = $v ;
    3036             }
    3037         }
    3038         return $flg ? array($min,$max) : false ;
     2771        $n = count($aLines);
     2772        if( $n == 0 ) return false;
     2773        $min = $aLines[0]->scaleposition ;
     2774        $max = $min ;
     2775        $flg = false;
     2776        for( $i=0; $i < $n; ++$i ) {
     2777            if( $aLines[$i]->direction == HORIZONTAL ) {
     2778                $flg = true ;
     2779                $v = $aLines[$i]->scaleposition ;
     2780                if( $min > $v ) $min = $v ;
     2781                if( $max < $v ) $max = $v ;
     2782            }
     2783        }
     2784        return $flg ? array($min,$max) : false ;
    30392785    }
    30402786
    30412787    // Get X min and max values for added lines
    30422788    function GetLinesXMinMax( $aLines ) {
    3043         $n = is_array($aLines) ? count($aLines) : 0;
    3044         if( $n == 0 ) return false ;
    3045         $min = $aLines[0]->scaleposition ;
    3046         $max = $min ;
    3047         $flg = false;
    3048         for( $i=0; $i < $n; ++$i ) {
    3049             if( $aLines[$i]->direction == VERTICAL ) {
    3050                 $flg = true ;
    3051                 $v = $aLines[$i]->scaleposition ;
    3052                 if( $min > $v ) $min = $v ;
    3053                 if( $max < $v ) $max = $v ;
    3054             }
    3055         }
    3056         return $flg ? array($min,$max) : false ;
     2789        $n = count($aLines);
     2790        if( $n == 0 ) return false ;
     2791        $min = $aLines[0]->scaleposition ;
     2792        $max = $min ;
     2793        $flg = false;
     2794        for( $i=0; $i < $n; ++$i ) {
     2795            if( $aLines[$i]->direction == VERTICAL ) {
     2796                $flg = true ;
     2797                $v = $aLines[$i]->scaleposition ;
     2798                if( $min > $v ) $min = $v ;
     2799                if( $max < $v ) $max = $v ;
     2800            }
     2801        }
     2802        return $flg ? array($min,$max) : false ;
    30572803    }
    30582804
    30592805    // Get min and max values for all included plots
    30602806    function GetPlotsYMinMax($aPlots) {
    3061         $n = count($aPlots);
    3062         $i=0;
    3063         do {
    3064             list($xmax,$max) = $aPlots[$i]->Max();
    3065         } while( ++$i < $n && !is_numeric($max) );
    3066 
    3067         $i=0;
    3068         do {
    3069             list($xmin,$min) = $aPlots[$i]->Min();
    3070         } while( ++$i < $n && !is_numeric($min) );
    3071 
    3072         if( !is_numeric($min) || !is_numeric($max) ) {
    3073             JpGraphError::RaiseL(25044);//('Cannot use autoscaling since it is impossible to determine a valid min/max value  of the Y-axis (only null values).');
    3074         }
    3075 
    3076         for($i=0; $i < $n; ++$i ) {
    3077             list($xmax,$ymax)=$aPlots[$i]->Max();
    3078             list($xmin,$ymin)=$aPlots[$i]->Min();
    3079             if (is_numeric($ymax)) $max=max($max,$ymax);
    3080             if (is_numeric($ymin)) $min=min($min,$ymin);
    3081         }
    3082         if( $min == '' ) $min = 0;
    3083         if( $max == '' ) $max = 0;
    3084         if( $min == 0 && $max == 0 ) {
    3085             // Special case if all values are 0
    3086             $min=0;$max=1;
    3087         }
    3088         return array($min,$max);
    3089     }
    3090 
    3091     function hasLinePlotAndBarPlot() {
    3092         $has_line = false;
    3093         $has_bar  = false;
    3094 
    3095         foreach ($this->plots as $plot) {
    3096             if ($plot instanceof LinePlot) {
    3097                 $has_line = true;
    3098             }
    3099             if ($plot instanceof BarPlot) {
    3100                 $has_bar = true;
    3101             }
    3102         }
    3103 
    3104         if ($has_line && $has_bar) {
    3105             return true;
    3106         }
    3107 
    3108         return false;
    3109     }
    3110 
    3111     function SetTheme($graph_theme) {
    3112 
    3113         if (!($this instanceof PieGraph)) {
    3114             if (!$this->isAfterSetScale) {
    3115                 JpGraphError::RaiseL(25133);//('Use Graph::SetTheme() after Graph::SetScale().');
    3116             }
    3117         }
    3118 
    3119         if ($this->graph_theme) {
    3120             $this->ClearTheme();
    3121         }
    3122         $this->graph_theme = $graph_theme;
    3123         $this->graph_theme->ApplyGraph($this);
    3124     }
    3125 
    3126     function ClearTheme() {
    3127         $this->graph_theme = null;
    3128 
    3129         $this->isRunningClear = true;
    3130 
    3131         $this->__construct(
    3132                 $this->inputValues['aWidth'],
    3133                 $this->inputValues['aHeight'],
    3134                 $this->inputValues['aCachedName'],
    3135                 $this->inputValues['aTimeout'],
    3136                 $this->inputValues['aInline']
    3137             );
    3138  
    3139         if (!($this instanceof PieGraph)) {
    3140             if ($this->isAfterSetScale) {
    3141                 $this->SetScale(
    3142                         $this->inputValues['aAxisType'],
    3143                         $this->inputValues['aYMin'],
    3144                         $this->inputValues['aYMax'],
    3145                         $this->inputValues['aXMin'],
    3146                         $this->inputValues['aXMax']
    3147                     );       
    3148             }
    3149         }
    3150 
    3151         $this->isRunningClear = false;
    3152     }
    3153 
    3154     function SetSupersampling($do = false, $scale = 2) {
    3155         if ($do) {
    3156             define('SUPERSAMPLING_SCALE', $scale);
    3157            // $this->img->scale = $scale;
    3158         } else {
    3159             define('SUPERSAMPLING_SCALE', 1);
    3160             //$this->img->scale = 0;
    3161         }
     2807        $n = count($aPlots);
     2808        $i=0;
     2809        do {
     2810            list($xmax,$max) = $aPlots[$i]->Max();
     2811        } while( ++$i < $n && !is_numeric($max) );
     2812
     2813        $i=0;
     2814        do {
     2815            list($xmin,$min) = $aPlots[$i]->Min();
     2816        } while( ++$i < $n && !is_numeric($min) );
     2817       
     2818        if( !is_numeric($min) || !is_numeric($max) ) {
     2819            JpGraphError::RaiseL(25044);//('Cannot use autoscaling since it is impossible to determine a valid min/max value  of the Y-axis (only null values).');
     2820        }
     2821
     2822        for($i=0; $i < $n; ++$i ) {
     2823            list($xmax,$ymax)=$aPlots[$i]->Max();
     2824            list($xmin,$ymin)=$aPlots[$i]->Min();
     2825            if (is_numeric($ymax)) $max=max($max,$ymax);
     2826            if (is_numeric($ymin)) $min=min($min,$ymin);
     2827        }
     2828        if( $min == '' ) $min = 0;
     2829        if( $max == '' ) $max = 0;
     2830        if( $min == 0 && $max == 0 ) {
     2831            // Special case if all values are 0
     2832            $min=0;$max=1;                     
     2833        }
     2834        return array($min,$max);
    31622835    }
    31632836
     
    31692842//===================================================
    31702843class LineProperty {
    3171     public $iWeight=1, $iColor='black', $iStyle='solid', $iShow=false;
    3172 
    3173     function __construct($aWeight=1,$aColor='black',$aStyle='solid') {
    3174         $this->iWeight = $aWeight;
    3175         $this->iColor = $aColor;
    3176         $this->iStyle = $aStyle;
    3177     }
    3178 
     2844    public $iWeight=1, $iColor="black",$iStyle="solid",$iShow=true;
     2845       
     2846//---------------
     2847// PUBLIC METHODS       
    31792848    function SetColor($aColor) {
    3180         $this->iColor = $aColor;
    3181     }
    3182 
     2849        $this->iColor = $aColor;
     2850    }
     2851       
    31832852    function SetWeight($aWeight) {
    3184         $this->iWeight = $aWeight;
    3185     }
    3186 
     2853        $this->iWeight = $aWeight;
     2854    }
     2855       
    31872856    function SetStyle($aStyle) {
    3188         $this->iStyle = $aStyle;
    3189     }
    3190 
     2857        $this->iStyle = $aStyle;
     2858    }
     2859               
    31912860    function Show($aShow=true) {
    3192         $this->iShow=$aShow;
    3193     }
    3194 
     2861        $this->iShow=$aShow;
     2862    }
     2863       
    31952864    function Stroke($aImg,$aX1,$aY1,$aX2,$aY2) {
    3196         if( $this->iShow ) {
    3197             $aImg->PushColor($this->iColor);
    3198             $oldls = $aImg->line_style;
    3199             $oldlw = $aImg->line_weight;
    3200             $aImg->SetLineWeight($this->iWeight);
    3201             $aImg->SetLineStyle($this->iStyle);
    3202             $aImg->StyleLine($aX1,$aY1,$aX2,$aY2);
    3203             $aImg->PopColor($this->iColor);
    3204             $aImg->line_style = $oldls;
    3205             $aImg->line_weight = $oldlw;
    3206 
    3207         }
     2865        if( $this->iShow ) {
     2866            $aImg->PushColor($this->iColor);
     2867            $oldls = $aImg->line_style;
     2868            $oldlw = $aImg->line_weight;
     2869            $aImg->SetLineWeight($this->iWeight);
     2870            $aImg->SetLineStyle($this->iStyle);                 
     2871            $aImg->StyleLine($aX1,$aY1,$aX2,$aY2);
     2872            $aImg->PopColor($this->iColor);
     2873            $aImg->line_style = $oldls;
     2874            $aImg->line_weight = $oldlw;
     2875
     2876        }
    32082877    }
    32092878}
    32102879
    3211 //===================================================
    3212 // CLASS GraphTabTitle
    3213 // Description: Draw "tab" titles on top of graphs
    3214 //===================================================
    32152880class GraphTabTitle extends Text{
    32162881    private $corner = 6 , $posx = 7, $posy = 4;
    32172882    private $fillcolor='lightyellow',$bordercolor='black';
    32182883    private $align = 'left', $width=TABTITLE_WIDTHFIT;
    3219     function __construct() {
    3220         $this->t = '';
    3221         $this->font_style = FS_BOLD;
    3222         $this->hide = true;
    3223         $this->color = 'darkred';
     2884    function GraphTabTitle() {
     2885        $this->t = '';
     2886        $this->font_style = FS_BOLD;
     2887        $this->hide = true;
     2888        $this->color = 'darkred';
    32242889    }
    32252890
    32262891    function SetColor($aTxtColor,$aFillColor='lightyellow',$aBorderColor='black') {
    3227         $this->color = $aTxtColor;
    3228         $this->fillcolor = $aFillColor;
    3229         $this->bordercolor = $aBorderColor;
     2892        $this->color = $aTxtColor;
     2893        $this->fillcolor = $aFillColor;
     2894        $this->bordercolor = $aBorderColor;
    32302895    }
    32312896
    32322897    function SetFillColor($aFillColor) {
    3233         $this->fillcolor = $aFillColor;
     2898        $this->fillcolor = $aFillColor;
    32342899    }
    32352900
    32362901    function SetTabAlign($aAlign) {
    3237         $this->align = $aAlign;
    3238     }
    3239 
     2902        $this->align = $aAlign;
     2903    }
     2904   
    32402905    function SetWidth($aWidth) {
    3241         $this->width = $aWidth ;
     2906        $this->width = $aWidth ;
    32422907    }
    32432908
    32442909    function Set($t) {
    3245         $this->t = $t;
    3246         $this->hide = false;
     2910        $this->t = $t;
     2911        $this->hide = false;
    32472912    }
    32482913
    32492914    function SetCorner($aD) {
    3250         $this->corner = $aD ;
     2915        $this->corner = $aD ;
    32512916    }
    32522917
    32532918    function Stroke($aImg,$aDummy1=null,$aDummy2=null) {
    3254         if( $this->hide )
    3255             return;
    3256         $this->boxed = false;
    3257         $w = $this->GetWidth($aImg) + 2*$this->posx;
    3258         $h = $this->GetTextHeight($aImg) + 2*$this->posy;
    3259 
    3260         $x = $aImg->left_margin;
    3261         $y = $aImg->top_margin;
    3262 
    3263         if( $this->width === TABTITLE_WIDTHFIT ) {
    3264             if( $this->align == 'left' ) {
    3265                 $p = array($x,                $y,
    3266                 $x,                $y-$h+$this->corner,
    3267                 $x + $this->corner,$y-$h,
    3268                 $x + $w - $this->corner, $y-$h,
    3269                 $x + $w, $y-$h+$this->corner,
    3270                 $x + $w, $y);
    3271             }
    3272             elseif( $this->align == 'center' ) {
    3273                 $x += round($aImg->plotwidth/2) - round($w/2);
    3274                 $p = array($x, $y,
    3275                 $x, $y-$h+$this->corner,
    3276                 $x + $this->corner, $y-$h,
    3277                 $x + $w - $this->corner, $y-$h,
    3278                 $x + $w, $y-$h+$this->corner,
    3279                 $x + $w, $y);
    3280             }
    3281             else {
    3282                 $x += $aImg->plotwidth -$w;
    3283                 $p = array($x, $y,
    3284                 $x, $y-$h+$this->corner,
    3285                 $x + $this->corner,$y-$h,
    3286                 $x + $w - $this->corner, $y-$h,
    3287                 $x + $w, $y-$h+$this->corner,
    3288                 $x + $w, $y);
    3289             }
    3290         }
    3291         else {
    3292             if( $this->width === TABTITLE_WIDTHFULL ) {
    3293                 $w = $aImg->plotwidth ;
    3294             }
    3295             else {
    3296                 $w = $this->width ;
    3297             }
    3298 
    3299             // Make the tab fit the width of the plot area
    3300             $p = array($x, $y,
    3301             $x, $y-$h+$this->corner,
    3302             $x + $this->corner,$y-$h,
    3303             $x + $w - $this->corner, $y-$h,
    3304             $x + $w, $y-$h+$this->corner,
    3305             $x + $w, $y);
    3306 
    3307         }
    3308         if( $this->halign == 'left' ) {
    3309             $aImg->SetTextAlign('left','bottom');
    3310             $x += $this->posx;
    3311             $y -= $this->posy;
    3312         }
    3313         elseif( $this->halign == 'center' ) {
    3314             $aImg->SetTextAlign('center','bottom');
    3315             $x += $w/2;
    3316             $y -= $this->posy;
    3317         }
    3318         else {
    3319             $aImg->SetTextAlign('right','bottom');
    3320             $x += $w - $this->posx;
    3321             $y -= $this->posy;
    3322         }
    3323 
    3324         $aImg->SetColor($this->fillcolor);
    3325         $aImg->FilledPolygon($p);
    3326 
    3327         $aImg->SetColor($this->bordercolor);
    3328         $aImg->Polygon($p,true);
    3329 
    3330         $aImg->SetColor($this->color);
    3331         $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
    3332         $aImg->StrokeText($x,$y,$this->t,0,'center');
     2919        if( $this->hide )
     2920            return;
     2921        $this->boxed = false;
     2922        $w = $this->GetWidth($aImg) + 2*$this->posx;
     2923        $h = $this->GetTextHeight($aImg) + 2*$this->posy;
     2924
     2925        $x = $aImg->left_margin;
     2926        $y = $aImg->top_margin;
     2927
     2928        if( $this->width === TABTITLE_WIDTHFIT ) {
     2929            if( $this->align == 'left' ) {
     2930                $p = array($x,                $y,
     2931                           $x,                $y-$h+$this->corner,
     2932                           $x + $this->corner,$y-$h,
     2933                           $x + $w - $this->corner, $y-$h,
     2934                           $x + $w, $y-$h+$this->corner,
     2935                           $x + $w, $y);
     2936            }
     2937            elseif( $this->align == 'center' ) {
     2938                $x += round($aImg->plotwidth/2) - round($w/2);
     2939                $p = array($x, $y,
     2940                           $x, $y-$h+$this->corner,
     2941                           $x + $this->corner, $y-$h,
     2942                           $x + $w - $this->corner, $y-$h,
     2943                           $x + $w, $y-$h+$this->corner,
     2944                           $x + $w, $y);
     2945            }
     2946            else {
     2947                $x += $aImg->plotwidth -$w;
     2948                $p = array($x, $y,
     2949                           $x, $y-$h+$this->corner,
     2950                           $x + $this->corner,$y-$h,
     2951                           $x + $w - $this->corner, $y-$h,
     2952                           $x + $w, $y-$h+$this->corner,
     2953                           $x + $w, $y);
     2954            }
     2955        }
     2956        else {
     2957            if( $this->width === TABTITLE_WIDTHFULL )
     2958                $w = $aImg->plotwidth ;
     2959            else
     2960                $w = $this->width ;
     2961
     2962            // Make the tab fit the width of the plot area
     2963            $p = array($x,                $y,
     2964                       $x,                $y-$h+$this->corner,
     2965                       $x + $this->corner,$y-$h,
     2966                       $x + $w - $this->corner, $y-$h,
     2967                       $x + $w, $y-$h+$this->corner,
     2968                       $x + $w, $y);
     2969           
     2970        }
     2971        if( $this->halign == 'left' ) {
     2972            $aImg->SetTextAlign('left','bottom');
     2973            $x += $this->posx;
     2974            $y -= $this->posy;
     2975        }
     2976        elseif( $this->halign == 'center' ) {
     2977            $aImg->SetTextAlign('center','bottom');
     2978            $x += $w/2;
     2979            $y -= $this->posy;
     2980        }
     2981        else {
     2982            $aImg->SetTextAlign('right','bottom');
     2983            $x += $w - $this->posx;
     2984            $y -= $this->posy;
     2985        }
     2986
     2987        $aImg->SetColor($this->fillcolor);
     2988        $aImg->FilledPolygon($p);
     2989
     2990        $aImg->SetColor($this->bordercolor);
     2991        $aImg->Polygon($p,true);
     2992       
     2993        $aImg->SetColor($this->color);
     2994        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
     2995        $aImg->StrokeText($x,$y,$this->t,0,'center');
    33332996    }
    33342997
     
    33403003//===================================================
    33413004class SuperScriptText extends Text {
    3342     private $iSuper='';
    3343     private $sfont_family='',$sfont_style='',$sfont_size=8;
     3005    private $iSuper="";
     3006    private $sfont_family="",$sfont_style="",$sfont_size=8;
    33443007    private $iSuperMargin=2,$iVertOverlap=4,$iSuperScale=0.65;
    33453008    private $iSDir=0;
    33463009    private $iSimple=false;
    33473010
    3348     function __construct($aTxt='',$aSuper='',$aXAbsPos=0,$aYAbsPos=0) {
    3349         parent::__construct($aTxt,$aXAbsPos,$aYAbsPos);
    3350         $this->iSuper = $aSuper;
     3011    function SuperScriptText($aTxt="",$aSuper="",$aXAbsPos=0,$aYAbsPos=0) {
     3012        parent::Text($aTxt,$aXAbsPos,$aYAbsPos);
     3013        $this->iSuper = $aSuper;
    33513014    }
    33523015
    33533016    function FromReal($aVal,$aPrecision=2) {
    3354         // Convert a floating point number to scientific notation
    3355         $neg=1.0;
    3356         if( $aVal < 0 ) {
    3357             $neg = -1.0;
    3358             $aVal = -$aVal;
    3359         }
    3360 
    3361         $l = floor(log10($aVal));
    3362         $a = sprintf("%0.".$aPrecision."f",round($aVal / pow(10,$l),$aPrecision));
    3363         $a *= $neg;
    3364         if( $this->iSimple && ($a == 1 || $a==-1) ) $a = '';
    3365 
    3366         if( $a != '' ) {
    3367             $this->t = $a.' * 10';
    3368         }
    3369         else {
    3370             if( $neg == 1 ) {
    3371                 $this->t = '10';
    3372             }
    3373             else {
    3374                 $this->t = '-10';
    3375             }
    3376         }
    3377         $this->iSuper = $l;
    3378     }
    3379 
    3380     function Set($aTxt,$aSuper='') {
    3381         $this->t = $aTxt;
    3382         $this->iSuper = $aSuper;
     3017        // Convert a floating point number to scientific notation
     3018        $neg=1.0;
     3019        if( $aVal < 0 ) {
     3020            $neg = -1.0;
     3021            $aVal = -$aVal;
     3022        }
     3023               
     3024        $l = floor(log10($aVal));
     3025        $a = sprintf("%0.".$aPrecision."f",round($aVal / pow(10,$l),$aPrecision));
     3026        $a *= $neg;
     3027        if( $this->iSimple && ($a == 1 || $a==-1) ) $a = '';
     3028       
     3029        if( $a != '' )
     3030            $this->t = $a.' * 10';
     3031        else {
     3032            if( $neg == 1 )
     3033                $this->t = '10';
     3034            else
     3035                $this->t = '-10';
     3036        }
     3037        $this->iSuper = $l;
     3038    }
     3039
     3040    function Set($aTxt,$aSuper="") {
     3041        $this->t = $aTxt;
     3042        $this->iSuper = $aSuper;
    33833043    }
    33843044
    33853045    function SetSuperFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=8) {
    3386         $this->sfont_family = $aFontFam;
    3387         $this->sfont_style = $aFontStyle;
    3388         $this->sfont_size = $aFontSize;
     3046        $this->sfont_family = $aFontFam;
     3047        $this->sfont_style = $aFontStyle;
     3048        $this->sfont_size = $aFontSize;
    33893049    }
    33903050
    33913051    // Total width of text
    33923052    function GetWidth($aImg) {
    3393         $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
    3394         $w = $aImg->GetTextWidth($this->t);
    3395         $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size);
    3396         $w += $aImg->GetTextWidth($this->iSuper);
    3397         $w += $this->iSuperMargin;
    3398         return $w;
    3399     }
    3400 
     3053        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
     3054        $w = $aImg->GetTextWidth($this->t);
     3055        $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size);
     3056        $w += $aImg->GetTextWidth($this->iSuper);
     3057        $w += $this->iSuperMargin;
     3058        return $w;
     3059    }
     3060       
    34013061    // Hight of font (approximate the height of the text)
    34023062    function GetFontHeight($aImg) {
    3403         $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
    3404         $h = $aImg->GetFontHeight();
    3405         $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size);
    3406         $h += $aImg->GetFontHeight();
    3407         return $h;
     3063        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); 
     3064        $h = $aImg->GetFontHeight();
     3065        $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size);
     3066        $h += $aImg->GetFontHeight();
     3067        return $h;
    34083068    }
    34093069
    34103070    // Hight of text
    34113071    function GetTextHeight($aImg) {
    3412         $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
    3413         $h = $aImg->GetTextHeight($this->t);
    3414         $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size);
    3415         $h += $aImg->GetTextHeight($this->iSuper);
    3416         return $h;
     3072        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
     3073        $h = $aImg->GetTextHeight($this->t);
     3074        $aImg->SetFont($this->sfont_family,$this->sfont_style,$this->sfont_size);
     3075        $h += $aImg->GetTextHeight($this->iSuper);
     3076        return $h;
    34173077    }
    34183078
    34193079    function Stroke($aImg,$ax=-1,$ay=-1) {
    3420 
     3080       
    34213081        // To position the super script correctly we need different
    3422         // cases to handle the alignmewnt specified since that will
    3423         // determine how we can interpret the x,y coordinates
    3424 
    3425         $w = parent::GetWidth($aImg);
    3426         $h = parent::GetTextHeight($aImg);
    3427         switch( $this->valign ) {
    3428             case 'top':
    3429                 $sy = $this->y;
    3430                 break;
    3431             case 'center':
    3432                 $sy = $this->y - $h/2;
    3433                 break;
    3434             case 'bottom':
    3435                 $sy = $this->y - $h;
    3436                 break;
    3437             default:
    3438                 JpGraphError::RaiseL(25052);//('PANIC: Internal error in SuperScript::Stroke(). Unknown vertical alignment for text');
    3439                 break;
    3440         }
    3441 
    3442         switch( $this->halign ) {
    3443             case 'left':
    3444                 $sx = $this->x + $w;
    3445                 break;
    3446             case 'center':
    3447                 $sx = $this->x + $w/2;
    3448                 break;
    3449             case 'right':
    3450                 $sx = $this->x;
    3451                 break;
    3452             default:
    3453                 JpGraphError::RaiseL(25053);//('PANIC: Internal error in SuperScript::Stroke(). Unknown horizontal alignment for text');
    3454                 break;
    3455         }
    3456 
    3457         $sx += $this->iSuperMargin;
    3458         $sy += $this->iVertOverlap;
    3459 
    3460         // Should we automatically determine the font or
    3461         // has the user specified it explicetly?
    3462         if( $this->sfont_family == '' ) {
    3463             if( $this->font_family <= FF_FONT2 ) {
    3464                 if( $this->font_family == FF_FONT0 ) {
    3465                     $sff = FF_FONT0;
    3466                 }
    3467                 elseif( $this->font_family == FF_FONT1 ) {
    3468                     if( $this->font_style == FS_NORMAL ) {
    3469                         $sff = FF_FONT0;
    3470                     }
    3471                     else {
    3472                         $sff = FF_FONT1;
    3473                     }
    3474                 }
    3475                 else {
    3476                     $sff = FF_FONT1;
    3477                 }
    3478                 $sfs = $this->font_style;
    3479                 $sfz = $this->font_size;
    3480             }
    3481             else {
    3482                 // TTF fonts
    3483                 $sff = $this->font_family;
    3484                 $sfs = $this->font_style;
    3485                 $sfz = floor($this->font_size*$this->iSuperScale);
    3486                 if( $sfz < 8 ) $sfz = 8;
    3487             }
    3488             $this->sfont_family = $sff;
    3489             $this->sfont_style = $sfs;
    3490             $this->sfont_size = $sfz;
    3491         }
    3492         else {
    3493             $sff = $this->sfont_family;
    3494             $sfs = $this->sfont_style;
    3495             $sfz = $this->sfont_size;
    3496         }
    3497 
    3498         parent::Stroke($aImg,$ax,$ay);
    3499 
    3500         // For the builtin fonts we need to reduce the margins
    3501         // since the bounding bx reported for the builtin fonts
    3502         // are much larger than for the TTF fonts.
    3503         if( $sff <= FF_FONT2 ) {
    3504             $sx -= 2;
    3505             $sy += 3;
    3506         }
    3507 
    3508         $aImg->SetTextAlign('left','bottom');
    3509         $aImg->SetFont($sff,$sfs,$sfz);
    3510         $aImg->PushColor($this->color);
    3511         $aImg->StrokeText($sx,$sy,$this->iSuper,$this->iSDir,'left');
    3512         $aImg->PopColor();
     3082        // cases to handle the alignmewnt specified since that will
     3083        // determine how we can interpret the x,y coordinates
     3084       
     3085        $w = parent::GetWidth($aImg);
     3086        $h = parent::GetTextHeight($aImg);
     3087        switch( $this->valign ) {
     3088            case 'top':
     3089                $sy = $this->y;
     3090                break;
     3091            case 'center':
     3092                $sy = $this->y - $h/2;
     3093                break;
     3094            case 'bottom':
     3095                $sy = $this->y - $h;
     3096                break;
     3097            default:
     3098                JpGraphError::RaiseL(25052);//('PANIC: Internal error in SuperScript::Stroke(). Unknown vertical alignment for text');
     3099                break;
     3100        }
     3101
     3102        switch( $this->halign ) {
     3103            case 'left':
     3104                $sx = $this->x + $w;
     3105                break;
     3106            case 'center':
     3107                $sx = $this->x + $w/2;
     3108                break;
     3109            case 'right':
     3110                $sx = $this->x;
     3111                break;
     3112            default:
     3113                JpGraphError::RaiseL(25053);//('PANIC: Internal error in SuperScript::Stroke(). Unknown horizontal alignment for text');
     3114                break;
     3115        }
     3116
     3117        $sx += $this->iSuperMargin;
     3118        $sy += $this->iVertOverlap;
     3119
     3120        // Should we automatically determine the font or
     3121        // has the user specified it explicetly?
     3122        if( $this->sfont_family == "" ) {
     3123            if( $this->font_family <= FF_FONT2 ) {
     3124                if( $this->font_family == FF_FONT0 ) {
     3125                    $sff = FF_FONT0;
     3126                }
     3127                elseif( $this->font_family == FF_FONT1 ) {
     3128                    if( $this->font_style == FS_NORMAL )
     3129                        $sff = FF_FONT0;
     3130                    else
     3131                        $sff = FF_FONT1;
     3132                }
     3133                else {
     3134                    $sff = FF_FONT1;
     3135                }
     3136                $sfs = $this->font_style;
     3137                $sfz = $this->font_size;
     3138            }
     3139            else {
     3140                // TTF fonts
     3141                $sff = $this->font_family;
     3142                $sfs = $this->font_style;
     3143                $sfz = floor($this->font_size*$this->iSuperScale);             
     3144                if( $sfz < 8 ) $sfz = 8;
     3145            }       
     3146            $this->sfont_family = $sff;
     3147            $this->sfont_style = $sfs;
     3148            $this->sfont_size = $sfz;       
     3149        }
     3150        else {
     3151            $sff = $this->sfont_family;
     3152            $sfs = $this->sfont_style;
     3153            $sfz = $this->sfont_size;       
     3154        }
     3155
     3156        parent::Stroke($aImg,$ax,$ay);
     3157
     3158
     3159        // For the builtin fonts we need to reduce the margins
     3160        // since the bounding bx reported for the builtin fonts
     3161        // are much larger than for the TTF fonts.
     3162        if( $sff <= FF_FONT2 ) {
     3163            $sx -= 2;
     3164            $sy += 3;
     3165        }
     3166
     3167        $aImg->SetTextAlign('left','bottom');   
     3168        $aImg->SetFont($sff,$sfs,$sfz);
     3169        $aImg->PushColor($this->color);
     3170        $aImg->StrokeText($sx,$sy,$this->iSuper,$this->iSDir,'left');
     3171        $aImg->PopColor();     
    35133172    }
    35143173}
     
    35223181    protected $img;
    35233182    protected $scale;
    3524     protected $majorcolor='#CCCCCC',$minorcolor='#DDDDDD';
    3525     protected $majortype='solid',$minortype='solid';
    3526     protected $show=false, $showMinor=false,$majorweight=1,$minorweight=1;
     3183    protected $grid_color='#DDDDDD',$grid_mincolor='#DDDDDD';
     3184    protected $type="solid";
     3185    protected $show=false, $showMinor=false,$weight=1;
    35273186    protected $fill=false,$fillcolor=array('#EFEFEF','#BBCCFF');
    3528 
    3529     function __construct($aAxis) {
    3530         $this->scale = $aAxis->scale;
    3531         $this->img = $aAxis->img;
    3532     }
    3533 
     3187//---------------
     3188// CONSTRUCTOR
     3189    function Grid($aAxis) {
     3190        $this->scale = $aAxis->scale;
     3191        $this->img = $aAxis->img;
     3192    }
     3193//---------------
     3194// PUBLIC METHODS
    35343195    function SetColor($aMajColor,$aMinColor=false) {
    3535         $this->majorcolor=$aMajColor;
    3536         if( $aMinColor === false ) {
    3537             $aMinColor = $aMajColor ;
    3538         }
    3539         $this->minorcolor = $aMinColor;
    3540     }
    3541 
    3542     function SetWeight($aMajorWeight,$aMinorWeight=1) {
    3543         $this->majorweight=$aMajorWeight;
    3544         $this->minorweight=$aMinorWeight;
    3545     }
    3546 
     3196        $this->grid_color=$aMajColor;
     3197        if( $aMinColor === false )
     3198            $aMinColor = $aMajColor ;
     3199        $this->grid_mincolor = $aMinColor;
     3200    }
     3201       
     3202    function SetWeight($aWeight) {
     3203        $this->weight=$aWeight;
     3204    }
     3205       
    35473206    // Specify if grid should be dashed, dotted or solid
    3548     function SetLineStyle($aMajorType,$aMinorType='solid') {
    3549         $this->majortype = $aMajorType;
    3550         $this->minortype = $aMinorType;
    3551     }
    3552 
    3553     function SetStyle($aMajorType,$aMinorType='solid') {
    3554         $this->SetLineStyle($aMajorType,$aMinorType);
    3555     }
    3556 
     3207    function SetLineStyle($aType) {
     3208        $this->type = $aType;
     3209    }
     3210       
    35573211    // Decide if both major and minor grid should be displayed
    35583212    function Show($aShowMajor=true,$aShowMinor=false) {
    3559         $this->show=$aShowMajor;
    3560         $this->showMinor=$aShowMinor;
    3561     }
    3562 
     3213        $this->show=$aShowMajor;
     3214        $this->showMinor=$aShowMinor;
     3215    }
     3216   
    35633217    function SetFill($aFlg=true,$aColor1='lightgray',$aColor2='lightblue') {
    3564         $this->fill = $aFlg;
    3565         $this->fillcolor = array( $aColor1, $aColor2 );
    3566     }
    3567 
     3218        $this->fill = $aFlg;
     3219        $this->fillcolor = array( $aColor1, $aColor2 );
     3220    }
     3221       
    35683222    // Display the grid
    35693223    function Stroke() {
    3570         if( $this->showMinor && !$this->scale->textscale ) {
    3571             $this->DoStroke($this->scale->ticks->ticks_pos,$this->minortype,$this->minorcolor,$this->minorweight);
    3572             $this->DoStroke($this->scale->ticks->maj_ticks_pos,$this->majortype,$this->majorcolor,$this->majorweight);
    3573         }
    3574         else {
    3575             $this->DoStroke($this->scale->ticks->maj_ticks_pos,$this->majortype,$this->majorcolor,$this->majorweight);
    3576         }
    3577     }
    3578 
    3579     //--------------
    3580     // Private methods
     3224        if( $this->showMinor && !$this->scale->textscale ) {
     3225            $tmp = $this->grid_color;
     3226            $this->grid_color = $this->grid_mincolor;
     3227            $this->DoStroke($this->scale->ticks->ticks_pos);
     3228
     3229            $this->grid_color = $tmp;
     3230            $this->DoStroke($this->scale->ticks->maj_ticks_pos);
     3231        }
     3232        else {
     3233            $this->DoStroke($this->scale->ticks->maj_ticks_pos);
     3234        }
     3235    }
     3236       
     3237//--------------
     3238// Private methods     
    35813239    // Draw the grid
    3582     function DoStroke($aTicksPos,$aType,$aColor,$aWeight) {
    3583         if( !$this->show ) return;
    3584         $nbrgrids = count($aTicksPos);
    3585 
    3586         if( $this->scale->type == 'y' ) {
    3587             $xl=$this->img->left_margin;
    3588             $xr=$this->img->width-$this->img->right_margin;
    3589 
    3590             if( $this->fill ) {
    3591                 // Draw filled areas
    3592                 $y2 = !empty($aTicksPos) ? $aTicksPos[0] : null;
    3593                 $i=1;
    3594                 while( $i < $nbrgrids ) {
    3595                     $y1 = $y2;
    3596                     $y2 = $aTicksPos[$i++];
    3597                     $this->img->SetColor($this->fillcolor[$i & 1]);
    3598                     $this->img->FilledRectangle($xl,$y1,$xr,$y2);
    3599                 }
    3600             }
    3601 
    3602             $this->img->SetColor($aColor);
    3603             $this->img->SetLineWeight($aWeight);
    3604 
    3605             // Draw grid lines
    3606             switch( $aType ) {
    3607                 case 'solid':  $style = LINESTYLE_SOLID; break;
    3608                 case 'dotted': $style = LINESTYLE_DOTTED; break;
    3609                 case 'dashed': $style = LINESTYLE_DASHED; break;
    3610                 case 'longdashed': $style = LINESTYLE_LONGDASH; break;
    3611                 default:
    3612                     $style = LINESTYLE_SOLID; break;
    3613             }
    3614 
    3615             for($i=0; $i < $nbrgrids; ++$i) {
    3616                 $y=$aTicksPos[$i];
    3617                 $this->img->StyleLine($xl,$y,$xr,$y,$style,true);
    3618             }
    3619         }
    3620         elseif( $this->scale->type == 'x' ) {
    3621             $yu=$this->img->top_margin;
    3622             $yl=$this->img->height-$this->img->bottom_margin;
    3623             $limit=$this->img->width-$this->img->right_margin;
    3624 
    3625             if( $this->fill ) {
    3626                 // Draw filled areas
    3627                 $x2 = $aTicksPos[0];
    3628                 $i=1;
    3629                 while( $i < $nbrgrids ) {
    3630                     $x1 = $x2;
    3631                     $x2 = min($aTicksPos[$i++],$limit) ;
    3632                     $this->img->SetColor($this->fillcolor[$i & 1]);
    3633                     $this->img->FilledRectangle($x1,$yu,$x2,$yl);
    3634                 }
    3635             }
    3636 
    3637             $this->img->SetColor($aColor);
    3638             $this->img->SetLineWeight($aWeight);
    3639 
    3640             // We must also test for limit since we might have
    3641             // an offset and the number of ticks is calculated with
    3642             // assumption offset==0 so we might end up drawing one
    3643             // to many gridlines
    3644             $i=0;
    3645             $x=$aTicksPos[$i];
    3646             while( $i<count($aTicksPos) && ($x=$aTicksPos[$i]) <= $limit ) {
    3647                 if    ( $aType == 'solid' )      $this->img->Line($x,$yl,$x,$yu);
    3648                 elseif( $aType == 'dotted' )     $this->img->DashedLineForGrid($x,$yl,$x,$yu,1,6);
    3649                 elseif( $aType == 'dashed' )     $this->img->DashedLineForGrid($x,$yl,$x,$yu,2,4);
    3650                 elseif( $aType == 'longdashed' ) $this->img->DashedLineForGrid($x,$yl,$x,$yu,8,6);
    3651                 ++$i;
    3652             }
    3653         }
    3654         else {
    3655             JpGraphError::RaiseL(25054,$this->scale->type);//('Internal error: Unknown grid axis ['.$this->scale->type.']');
    3656         }
    3657         return true;
     3240    function DoStroke($aTicksPos) {
     3241        if( !$this->show )
     3242            return;     
     3243        $nbrgrids = count($aTicksPos); 
     3244
     3245        if( $this->scale->type=="y" ) {
     3246            $xl=$this->img->left_margin;
     3247            $xr=$this->img->width-$this->img->right_margin;
     3248           
     3249            if( $this->fill ) {
     3250                // Draw filled areas
     3251                $y2 = $aTicksPos[0];
     3252                $i=1;
     3253                while( $i < $nbrgrids ) {
     3254                    $y1 = $y2;
     3255                    $y2 = $aTicksPos[$i++];
     3256                    $this->img->SetColor($this->fillcolor[$i & 1]);
     3257                    $this->img->FilledRectangle($xl,$y1,$xr,$y2);
     3258                }
     3259            }
     3260
     3261            $this->img->SetColor($this->grid_color);
     3262            $this->img->SetLineWeight($this->weight);
     3263
     3264            // Draw grid lines
     3265            switch( $this->type ) {
     3266                case "solid":  $style = LINESTYLE_SOLID; break;
     3267                case "dotted": $style = LINESTYLE_DOTTED; break;
     3268                case "dashed": $style = LINESTYLE_DASHED; break;
     3269                case "longdashed": $style = LINESTYLE_LONGDASH; break;
     3270                default:
     3271                    $style = LINESTYLE_SOLID; break;
     3272            }
     3273
     3274            for($i=0; $i < $nbrgrids; ++$i) {
     3275                $y=$aTicksPos[$i];
     3276                $this->img->StyleLine($xl,$y,$xr,$y,$style);
     3277            }
     3278        }
     3279        elseif( $this->scale->type=="x" ) {     
     3280            $yu=$this->img->top_margin;
     3281            $yl=$this->img->height-$this->img->bottom_margin;
     3282            $limit=$this->img->width-$this->img->right_margin;
     3283
     3284            if( $this->fill ) {
     3285                // Draw filled areas
     3286                $x2 = $aTicksPos[0];
     3287                $i=1;
     3288                while( $i < $nbrgrids ) {
     3289                    $x1 = $x2;
     3290                    $x2 = min($aTicksPos[$i++],$limit) ;
     3291                    $this->img->SetColor($this->fillcolor[$i & 1]);
     3292                    $this->img->FilledRectangle($x1,$yu,$x2,$yl);
     3293                }
     3294            }
     3295
     3296            $this->img->SetColor($this->grid_color);
     3297            $this->img->SetLineWeight($this->weight);
     3298
     3299            // We must also test for limit since we might have
     3300            // an offset and the number of ticks is calculated with
     3301            // assumption offset==0 so we might end up drawing one
     3302            // to many gridlines
     3303            $i=0;
     3304            $x=$aTicksPos[$i];     
     3305            while( $i<count($aTicksPos) && ($x=$aTicksPos[$i]) <= $limit ) {
     3306                if( $this->type == "solid" )                           
     3307                    $this->img->Line($x,$yl,$x,$yu);
     3308                elseif( $this->type == "dotted" )
     3309                    $this->img->DashedLine($x,$yl,$x,$yu,1,6);
     3310                elseif( $this->type == "dashed" )
     3311                    $this->img->DashedLine($x,$yl,$x,$yu,2,4);
     3312                elseif( $this->type == "longdashed" )
     3313                    $this->img->DashedLine($x,$yl,$x,$yu,8,6); 
     3314                ++$i; 
     3315            }
     3316        }       
     3317        else {
     3318            JpGraphError::RaiseL(25054,$this->scale->type);//('Internal error: Unknown grid axis ['.$this->scale->type.']');
     3319        }
     3320        return true;
    36583321    }
    36593322} // Class
     
    36653328// several occasion must know wheter it's an X or Y axis.
    36663329// This was a design decision to make the code easier to
    3667 // follow.
     3330// follow. 
    36683331//===================================================
    36693332class AxisPrototype {
    3670     public $scale=null;
     3333    public $scale=null; 
    36713334    public $img=null;
    36723335    public $hide=false,$hide_labels=false;
    36733336    public $title=null;
    3674     public $font_family=FF_DEFAULT,$font_style=FS_NORMAL,$font_size=8,$label_angle=0;
     3337    public $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12,$label_angle=0;
    36753338    public $tick_step=1;
    36763339    public $pos = false;
     
    36853348    protected $labelPos=0;   // Which side of the axis should the labels be?
    36863349    protected $title_adjust,$title_margin,$title_side=SIDE_LEFT;
    3687     protected $tick_label_margin=5;
     3350    protected $tick_label_margin=7;
    36883351    protected $label_halign = '',$label_valign = '', $label_para_align='left';
    36893352    protected $hide_line=false;
    36903353    protected $iDeltaAbsPos=0;
    36913354
    3692     function __construct($img,$aScale,$color = array(0,0,0)) {
    3693         $this->img = $img;
    3694         $this->scale = $aScale;
    3695         $this->color = $color;
    3696         $this->title=new Text('');
    3697 
    3698         if( $aScale->type == 'y' ) {
    3699             $this->title_margin = 25;
    3700             $this->title_adjust = 'middle';
    3701             $this->title->SetOrientation(90);
    3702             $this->tick_label_margin=7;
    3703             $this->labelPos=SIDE_LEFT;
    3704         }
    3705         else {
    3706             $this->title_margin = 5;
    3707             $this->title_adjust = 'high';
    3708             $this->title->SetOrientation(0);
    3709             $this->tick_label_margin=5;
    3710             $this->labelPos=SIDE_DOWN;
    3711             $this->title_side=SIDE_DOWN;
    3712         }
    3713     }
    3714 
     3355//---------------
     3356// CONSTRUCTOR
     3357    function Axis($img,$aScale,$color=array(0,0,0)) {
     3358        $this->img = $img;
     3359        $this->scale = $aScale;
     3360        $this->color = $color;
     3361        $this->title=new Text("");
     3362               
     3363        if( $aScale->type=="y" ) {
     3364            $this->title_margin = 25;
     3365            $this->title_adjust="middle";
     3366            $this->title->SetOrientation(90);
     3367            $this->tick_label_margin=7;
     3368            $this->labelPos=SIDE_LEFT;
     3369        }
     3370        else {
     3371            $this->title_margin = 5;
     3372            $this->title_adjust="high";
     3373            $this->title->SetOrientation(0);                   
     3374            $this->tick_label_margin=7;
     3375            $this->labelPos=SIDE_DOWN;
     3376            $this->title_side=SIDE_DOWN;
     3377        }
     3378    }
     3379//---------------
     3380// PUBLIC METHODS       
     3381       
    37153382    function SetLabelFormat($aFormStr) {
    3716         $this->scale->ticks->SetLabelFormat($aFormStr);
     3383        $this->scale->ticks->SetLabelFormat($aFormStr);
    37173384    }
    37183385
    37193386    function SetLabelFormatString($aFormStr,$aDate=false) {
    3720         $this->scale->ticks->SetLabelFormat($aFormStr,$aDate);
    3721     }
    3722 
     3387        $this->scale->ticks->SetLabelFormat($aFormStr,$aDate);
     3388    }
     3389       
    37233390    function SetLabelFormatCallback($aFuncName) {
    3724         $this->scale->ticks->SetFormatCallback($aFuncName);
    3725     }
    3726 
    3727     function SetLabelAlign($aHAlign,$aVAlign='top',$aParagraphAlign='left') {
    3728         $this->label_halign = $aHAlign;
    3729         $this->label_valign = $aVAlign;
    3730         $this->label_para_align = $aParagraphAlign;
    3731     }
     3391        $this->scale->ticks->SetFormatCallback($aFuncName);
     3392    }
     3393
     3394    function SetLabelAlign($aHAlign,$aVAlign="top",$aParagraphAlign='left') {
     3395        $this->label_halign = $aHAlign;
     3396        $this->label_valign = $aVAlign;
     3397        $this->label_para_align = $aParagraphAlign;
     3398    }           
    37323399
    37333400    // Don't display the first label
    37343401    function HideFirstTickLabel($aShow=false) {
    3735         $this->show_first_label=$aShow;
     3402        $this->show_first_label=$aShow;
    37363403    }
    37373404
    37383405    function HideLastTickLabel($aShow=false) {
    3739         $this->show_last_label=$aShow;
     3406        $this->show_last_label=$aShow;
    37403407    }
    37413408
    37423409    // Manually specify the major and (optional) minor tick position and labels
    37433410    function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) {
    3744         $this->scale->ticks->SetTickPositions($aMajPos,$aMinPos,$aLabels);
     3411        $this->scale->ticks->SetTickPositions($aMajPos,$aMinPos,$aLabels);
    37453412    }
    37463413
    37473414    // Manually specify major tick positions and optional labels
    37483415    function SetMajTickPositions($aMajPos,$aLabels=NULL) {
    3749         $this->scale->ticks->SetTickPositions($aMajPos,NULL,$aLabels);
     3416        $this->scale->ticks->SetTickPositions($aMajPos,NULL,$aLabels);
    37503417    }
    37513418
    37523419    // Hide minor or major tick marks
    37533420    function HideTicks($aHideMinor=true,$aHideMajor=true) {
    3754         $this->scale->ticks->SupressMinorTickMarks($aHideMinor);
    3755         $this->scale->ticks->SupressTickMarks($aHideMajor);
     3421        $this->scale->ticks->SupressMinorTickMarks($aHideMinor);
     3422        $this->scale->ticks->SupressTickMarks($aHideMajor);
    37563423    }
    37573424
    37583425    // Hide zero label
    37593426    function HideZeroLabel($aFlag=true) {
    3760         $this->scale->ticks->SupressZeroLabel();
    3761     }
    3762 
     3427        $this->scale->ticks->SupressZeroLabel();
     3428    }
     3429       
    37633430    function HideFirstLastLabel() {
    3764         // The two first calls to ticks method will supress
    3765         // automatically generated scale values. However, that
    3766         // will not affect manually specified value, e.g text-scales.
    3767         // therefor we also make a kludge here to supress manually
    3768         // specified scale labels.
    3769         $this->scale->ticks->SupressLast();
    3770         $this->scale->ticks->SupressFirst();
    3771         $this->show_first_label = false;
    3772         $this->show_last_label = false;
    3773     }
    3774 
     3431        // The two first calls to ticks method will supress
     3432        // automatically generated scale values. However, that
     3433        // will not affect manually specified value, e.g text-scales.
     3434        // therefor we also make a kludge here to supress manually
     3435        // specified scale labels.
     3436        $this->scale->ticks->SupressLast();
     3437        $this->scale->ticks->SupressFirst();
     3438        $this->show_first_label = false;
     3439        $this->show_last_label = false;
     3440    }
     3441       
    37753442    // Hide the axis
    37763443    function Hide($aHide=true) {
    3777         $this->hide=$aHide;
     3444        $this->hide=$aHide;
    37783445    }
    37793446
    37803447    // Hide the actual axis-line, but still print the labels
    37813448    function HideLine($aHide=true) {
    3782         $this->hide_line = $aHide;
     3449        $this->hide_line = $aHide;
    37833450    }
    37843451
    37853452    function HideLabels($aHide=true) {
    3786         $this->hide_labels = $aHide;
    3787     }
     3453        $this->hide_labels = $aHide;
     3454    }
     3455   
    37883456
    37893457    // Weight of axis
    37903458    function SetWeight($aWeight) {
    3791         $this->weight = $aWeight;
     3459        $this->weight = $aWeight;
    37923460    }
    37933461
    37943462    // Axis color
    37953463    function SetColor($aColor,$aLabelColor=false) {
    3796         $this->color = $aColor;
    3797         if( !$aLabelColor ) $this->label_color = $aColor;
    3798         else $this->label_color = $aLabelColor;
    3799     }
    3800 
     3464        $this->color = $aColor;
     3465        if( !$aLabelColor ) $this->label_color = $aColor;
     3466        else $this->label_color = $aLabelColor;
     3467    }
     3468       
    38013469    // Title on axis
    3802     function SetTitle($aTitle,$aAdjustAlign='high') {
    3803         $this->title->Set($aTitle);
    3804         $this->title_adjust=$aAdjustAlign;
    3805     }
    3806 
     3470    function SetTitle($aTitle,$aAdjustAlign="high") {
     3471        $this->title->Set($aTitle);
     3472        $this->title_adjust=$aAdjustAlign;
     3473    }
     3474       
    38073475    // Specify distance from the axis
    38083476    function SetTitleMargin($aMargin) {
    3809         $this->title_margin=$aMargin;
    3810     }
    3811 
     3477        $this->title_margin=$aMargin;
     3478    }
     3479       
    38123480    // Which side of the axis should the axis title be?
    38133481    function SetTitleSide($aSideOfAxis) {
    3814         $this->title_side = $aSideOfAxis;
    3815     }
    3816 
     3482        $this->title_side = $aSideOfAxis;
     3483    }
     3484
     3485    // Utility function to set the direction for tick marks
     3486    function SetTickDirection($aDir) {
     3487        // Will be deprecated from 1.7         
     3488        if( ERR_DEPRECATED )
     3489            JpGraphError::RaiseL(25055);//('Axis::SetTickDirection() is deprecated. Use Axis::SetTickSide() instead');
     3490        $this->scale->ticks->SetSide($aDir);
     3491    }
     3492   
    38173493    function SetTickSide($aDir) {
    3818         $this->scale->ticks->SetSide($aDir);
    3819     }
    3820 
    3821     function SetTickSize($aMajSize,$aMinSize=3) {
    3822         $this->scale->ticks->SetSize($aMajSize,$aMinSize=3);
    3823     }
    3824 
     3494        $this->scale->ticks->SetSide($aDir);
     3495    }
     3496       
    38253497    // Specify text labels for the ticks. One label for each data point
    38263498    function SetTickLabels($aLabelArray,$aLabelColorArray=null) {
    3827         $this->ticks_label = $aLabelArray;
    3828         $this->ticks_label_colors = $aLabelColorArray;
     3499        $this->ticks_label = $aLabelArray;
     3500        $this->ticks_label_colors = $aLabelColorArray;
     3501    }
     3502       
     3503    // How far from the axis should the labels be drawn
     3504    function SetTickLabelMargin($aMargin) {
     3505        if( ERR_DEPRECATED )           
     3506            JpGraphError::RaiseL(25056);//('SetTickLabelMargin() is deprecated. Use Axis::SetLabelMargin() instead.');
     3507        $this->tick_label_margin=$aMargin;
    38293508    }
    38303509
    38313510    function SetLabelMargin($aMargin) {
    3832         $this->tick_label_margin=$aMargin;
    3833     }
    3834 
     3511        $this->tick_label_margin=$aMargin;
     3512    }
     3513       
    38353514    // Specify that every $step of the ticks should be displayed starting
    38363515    // at $start
     3516    // DEPRECATED FUNCTION: USE SetTextTickInterval() INSTEAD
     3517    function SetTextTicks($step,$start=0) {
     3518        JpGraphError::RaiseL(25057);//(" SetTextTicks() is deprecated. Use SetTextTickInterval() instead.");           
     3519    }
     3520
     3521    // Specify that every $step of the ticks should be displayed starting
     3522    // at $start       
    38373523    function SetTextTickInterval($aStep,$aStart=0) {
    3838         $this->scale->ticks->SetTextLabelStart($aStart);
    3839         $this->tick_step=$aStep;
    3840     }
    3841 
    3842     // Specify that every $step tick mark should have a label
     3524        $this->scale->ticks->SetTextLabelStart($aStart);
     3525        $this->tick_step=$aStep;
     3526    }
     3527         
     3528    // Specify that every $step tick mark should have a label 
    38433529    // should be displayed starting
    38443530    function SetTextLabelInterval($aStep) {
    3845         if( $aStep < 1 ) {
    3846             JpGraphError::RaiseL(25058);//(" Text label interval must be specified >= 1.");
    3847         }
    3848         $this->label_step=$aStep;
    3849     }
    3850 
     3531        if( $aStep < 1 )
     3532            JpGraphError::RaiseL(25058);//(" Text label interval must be specified >= 1.");
     3533        $this->label_step=$aStep;
     3534    }
     3535       
     3536    // Which side of the axis should the labels be on?
     3537    function SetLabelPos($aSidePos) {
     3538        // This will be deprecated from 1.7
     3539        if( ERR_DEPRECATED )           
     3540            JpGraphError::RaiseL(25059);//('SetLabelPos() is deprecated. Use Axis::SetLabelSide() instead.');
     3541        $this->labelPos=$aSidePos;
     3542    }
     3543   
    38513544    function SetLabelSide($aSidePos) {
    3852         $this->labelPos=$aSidePos;
     3545        $this->labelPos=$aSidePos;
    38533546    }
    38543547
    38553548    // Set the font
    38563549    function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) {
    3857         $this->font_family = $aFamily;
    3858         $this->font_style = $aStyle;
    3859         $this->font_size = $aSize;
     3550        $this->font_family = $aFamily;
     3551        $this->font_style = $aStyle;
     3552        $this->font_size = $aSize;
    38603553    }
    38613554
    38623555    // Position for axis line on the "other" scale
    38633556    function SetPos($aPosOnOtherScale) {
    3864         $this->pos=$aPosOnOtherScale;
    3865     }
    3866 
    3867     // Set the position of the axis to be X-pixels delta to the right
     3557        $this->pos=$aPosOnOtherScale;
     3558    }
     3559
     3560    // Set the position of the axis to be X-pixels delta to the right 
    38683561    // of the max X-position (used to position the multiple Y-axis)
    38693562    function SetPosAbsDelta($aDelta) {
    3870         $this->iDeltaAbsPos=$aDelta;
    3871     }
    3872 
     3563      $this->iDeltaAbsPos=$aDelta;
     3564    }
     3565       
    38733566    // Specify the angle for the tick labels
    38743567    function SetLabelAngle($aAngle) {
    3875         $this->label_angle = $aAngle;
    3876     }
     3568        $this->label_angle = $aAngle;
     3569    }   
    38773570
    38783571} // Class
     
    38853578// several occasion must know wheter it's an X or Y axis.
    38863579// This was a design decision to make the code easier to
    3887 // follow.
     3580// follow. 
    38883581//===================================================
    38893582class Axis extends AxisPrototype {
    38903583
    3891     function __construct($img,$aScale,$color='black') {
    3892         parent::__construct($img,$aScale,$color);
    3893     }
    3894 
     3584    function Axis($img,$aScale,$color=array(0,0,0)) {
     3585        parent::Axis($img,$aScale,$color);
     3586    }
     3587       
    38953588    // Stroke the axis.
    3896     function Stroke($aOtherAxisScale,$aStrokeLabels=true) {
    3897         if( $this->hide )
    3898             return;
    3899         if( is_numeric($this->pos) ) {
    3900             $pos=$aOtherAxisScale->Translate($this->pos);
    3901         }
    3902         else { // Default to minimum of other scale if pos not set
    3903             if( ($aOtherAxisScale->GetMinVal() >= 0 && $this->pos==false) || $this->pos == 'min' ) {
    3904                 $pos = $aOtherAxisScale->scale_abs[0];
    3905             }
    3906             elseif($this->pos == "max") {
    3907                 $pos = $aOtherAxisScale->scale_abs[1];
    3908             }
    3909             else { // If negative set x-axis at 0
    3910                 $this->pos=0;
    3911                 $pos=$aOtherAxisScale->Translate(0);
    3912             }
    3913         }
    3914 
    3915         $pos += $this->iDeltaAbsPos;
    3916         $this->img->SetLineWeight($this->weight);
    3917         $this->img->SetColor($this->color);
    3918         $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
    3919 
    3920         if( $this->scale->type == "x" ) {
    3921             if( !$this->hide_line ) {
    3922                 // Stroke X-axis
    3923                 $this->img->FilledRectangle(
    3924                     $this->img->left_margin,
    3925                     $pos,
    3926                     $this->img->width - $this->img->right_margin,
    3927                     $pos + $this->weight-1
    3928                 );
    3929             }
    3930             if( $this->title_side == SIDE_DOWN ) {
    3931                 $y = $pos + $this->img->GetFontHeight() + $this->title_margin + $this->title->margin;
    3932                 $yalign = 'top';
    3933             }
    3934             else {
    3935                 $y = $pos - $this->img->GetFontHeight() - $this->title_margin - $this->title->margin;
    3936                 $yalign = 'bottom';
    3937             }
    3938 
    3939             if( $this->title_adjust=='high' ) {
    3940                 $this->title->SetPos($this->img->width-$this->img->right_margin,$y,'right',$yalign);
    3941             }
    3942             elseif( $this->title_adjust=='middle' || $this->title_adjust=='center' ) {
    3943                 $this->title->SetPos(($this->img->width-$this->img->left_margin-$this->img->right_margin)/2+$this->img->left_margin,$y,'center',$yalign);
    3944             }
    3945             elseif($this->title_adjust=='low') {
    3946                 $this->title->SetPos($this->img->left_margin,$y,'left',$yalign);
    3947             }
    3948             else {
    3949                 JpGraphError::RaiseL(25060,$this->title_adjust);//('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')');
    3950             }
    3951         }
    3952         elseif( $this->scale->type == "y" ) {
    3953             // Add line weight to the height of the axis since
    3954             // the x-axis could have a width>1 and we want the axis to fit nicely together.
    3955             if( !$this->hide_line ) {
    3956                 // Stroke Y-axis
    3957                 $this->img->FilledRectangle(
    3958                     $pos - $this->weight + 1,
    3959                     $this->img->top_margin,
    3960                     $pos,
    3961                     $this->img->height - $this->img->bottom_margin + $this->weight - 1
    3962                 );
    3963             }
    3964 
    3965             $x=$pos ;
    3966             if( $this->title_side == SIDE_LEFT ) {
    3967                 $x -= $this->title_margin;
    3968                 $x -= $this->title->margin;
    3969                 $halign = 'right';
    3970             }
    3971             else {
    3972                 $x += $this->title_margin;
    3973                 $x += $this->title->margin;
    3974                 $halign = 'left';
    3975             }
    3976             // If the user has manually specified an hor. align
    3977             // then we override the automatic settings with this
    3978             // specifed setting. Since default is 'left' we compare
    3979             // with that. (This means a manually set 'left' align
    3980             // will have no effect.)
    3981             if( $this->title->halign != 'left' ) {
    3982                 $halign = $this->title->halign;
    3983             }
    3984             if( $this->title_adjust == 'high' ) {
    3985                 $this->title->SetPos($x,$this->img->top_margin,$halign,'top');
    3986             }
    3987             elseif($this->title_adjust=='middle' || $this->title_adjust=='center') {
    3988                 $this->title->SetPos($x,($this->img->height-$this->img->top_margin-$this->img->bottom_margin)/2+$this->img->top_margin,$halign,"center");
    3989             }
    3990             elseif($this->title_adjust=='low') {
    3991                 $this->title->SetPos($x,$this->img->height-$this->img->bottom_margin,$halign,'bottom');
    3992             }
    3993             else {
    3994                 JpGraphError::RaiseL(25061,$this->title_adjust);//('Unknown alignment specified for Y-axis title. ('.$this->title_adjust.')');
    3995             }
    3996         }
    3997         $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
    3998         if( $aStrokeLabels ) {
    3999             if( !$this->hide_labels ) {
    4000                 $this->StrokeLabels($pos);
    4001             }
    4002             $this->title->Stroke($this->img);
    4003         }
    4004     }
    4005 
    4006     //---------------
    4007     // PRIVATE METHODS
     3589    function Stroke($aOtherAxisScale,$aStrokeLabels=true) {             
     3590        if( $this->hide ) return;               
     3591        if( is_numeric($this->pos) ) {
     3592            $pos=$aOtherAxisScale->Translate($this->pos);
     3593        }
     3594        else {  // Default to minimum of other scale if pos not set             
     3595            if( ($aOtherAxisScale->GetMinVal() >= 0 && $this->pos==false) || $this->pos=="min" ) {
     3596                $pos = $aOtherAxisScale->scale_abs[0];
     3597            }
     3598            elseif($this->pos == "max") {
     3599                $pos = $aOtherAxisScale->scale_abs[1];
     3600            }
     3601            else { // If negative set x-axis at 0
     3602                $this->pos=0;
     3603                $pos=$aOtherAxisScale->Translate(0);
     3604            }
     3605        }
     3606        $pos += $this->iDeltaAbsPos;   
     3607        $this->img->SetLineWeight($this->weight);
     3608        $this->img->SetColor($this->color);             
     3609        $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
     3610        if( $this->scale->type == "x" ) {
     3611            if( !$this->hide_line )
     3612                $this->img->FilledRectangle($this->img->left_margin,$pos,
     3613                                            $this->img->width-$this->img->right_margin,$pos+$this->weight-1);
     3614            if( $this->title_side == SIDE_DOWN ) {
     3615                $y = $pos + $this->img->GetFontHeight() + $this->title_margin + $this->title->margin;
     3616                $yalign = 'top';
     3617            }
     3618            else {
     3619                $y = $pos - $this->img->GetFontHeight() - $this->title_margin - $this->title->margin;
     3620                $yalign = 'bottom';
     3621            }
     3622
     3623            if( $this->title_adjust=='high' )
     3624                $this->title->SetPos($this->img->width-$this->img->right_margin,$y,'right',$yalign);
     3625            elseif( $this->title_adjust=='middle' || $this->title_adjust=='center' )
     3626                $this->title->SetPos(($this->img->width-$this->img->left_margin-$this->img->right_margin)/2+$this->img->left_margin,$y,'center',$yalign);
     3627            elseif($this->title_adjust=='low')
     3628                $this->title->SetPos($this->img->left_margin,$y,'left',$yalign);
     3629            else {     
     3630                JpGraphError::RaiseL(25060,$this->title_adjust);//('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')');
     3631            }
     3632        }
     3633        elseif( $this->scale->type == "y" ) {
     3634            // Add line weight to the height of the axis since
     3635            // the x-axis could have a width>1 and we want the axis to fit nicely together.
     3636            if( !$this->hide_line )
     3637                $this->img->FilledRectangle($pos-$this->weight+1,$this->img->top_margin,
     3638                                            $pos,$this->img->height-$this->img->bottom_margin+$this->weight-1);
     3639            $x=$pos ;
     3640            if( $this->title_side == SIDE_LEFT ) {
     3641                $x -= $this->title_margin;
     3642                $x -= $this->title->margin;
     3643                $halign="right";
     3644            }
     3645            else {
     3646                $x += $this->title_margin;
     3647                $x += $this->title->margin;
     3648                $halign="left";
     3649            }
     3650            // If the user has manually specified an hor. align
     3651            // then we override the automatic settings with this
     3652            // specifed setting. Since default is 'left' we compare
     3653            // with that. (This means a manually set 'left' align
     3654            // will have no effect.)
     3655            if( $this->title->halign != 'left' )
     3656                $halign = $this->title->halign;
     3657            if( $this->title_adjust=="high" )
     3658                $this->title->SetPos($x,$this->img->top_margin,$halign,"top");
     3659            elseif($this->title_adjust=="middle" || $this->title_adjust=="center") 
     3660                $this->title->SetPos($x,($this->img->height-$this->img->top_margin-$this->img->bottom_margin)/2+$this->img->top_margin,$halign,"center");
     3661            elseif($this->title_adjust=="low")
     3662                $this->title->SetPos($x,$this->img->height-$this->img->bottom_margin,$halign,"bottom");
     3663            else       
     3664                JpGraphError::RaiseL(25061,$this->title_adjust);//('Unknown alignment specified for Y-axis title. ('.$this->title_adjust.')');
     3665               
     3666        }
     3667        $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
     3668        if( $aStrokeLabels ) {
     3669            if( !$this->hide_labels )
     3670                $this->StrokeLabels($pos);
     3671            $this->title->Stroke($this->img);
     3672        }
     3673    }
     3674
     3675//---------------
     3676// PRIVATE METHODS     
    40083677    // Draw all the tick labels on major tick marks
    40093678    function StrokeLabels($aPos,$aMinor=false,$aAbsLabel=false) {
    40103679
    4011         if( is_array($this->label_color) && count($this->label_color) > 3 ) {
    4012             $this->ticks_label_colors = $this->label_color;
    4013             $this->img->SetColor($this->label_color[0]);
    4014         }
    4015         else {
    4016             $this->img->SetColor($this->label_color);
    4017         }
    4018         $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
    4019         $yoff=$this->img->GetFontHeight()/2;
    4020 
    4021         // Only draw labels at major tick marks
    4022         $nbr = count($this->scale->ticks->maj_ticks_label);
    4023 
    4024         // We have the option to not-display the very first mark
    4025         // (Usefull when the first label might interfere with another
    4026         // axis.)
    4027         $i = $this->show_first_label ? 0 : 1 ;
    4028         if( !$this->show_last_label ) {
    4029             --$nbr;
    4030         }
    4031         // Now run through all labels making sure we don't overshoot the end
    4032         // of the scale.
    4033         $ncolor=0;
    4034         if( isset($this->ticks_label_colors) ) {
    4035             $ncolor=count($this->ticks_label_colors);
    4036         }
    4037         while( $i < $nbr ) {
    4038             // $tpos holds the absolute text position for the label
    4039             $tpos=$this->scale->ticks->maj_ticklabels_pos[$i];
    4040 
    4041             // Note. the $limit is only used for the x axis since we
    4042             // might otherwise overshoot if the scale has been centered
    4043             // This is due to us "loosing" the last tick mark if we center.
    4044             if( $this->scale->type == 'x' && $tpos > $this->img->width-$this->img->right_margin+1 ) {
    4045                 return;
    4046             }
    4047             // we only draw every $label_step label
    4048             if( ($i % $this->label_step)==0 ) {
    4049 
    4050                 // Set specific label color if specified
    4051                 if( $ncolor > 0 ) {
    4052                     $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]);
    4053                 }
    4054 
    4055                 // If the label has been specified use that and in other case
    4056                 // just label the mark with the actual scale value
    4057                 $m=$this->scale->ticks->GetMajor();
    4058 
    4059                 // ticks_label has an entry for each data point and is the array
    4060                 // that holds the labels set by the user. If the user hasn't
    4061                 // specified any values we use whats in the automatically asigned
    4062                 // labels in the maj_ticks_label
    4063                 if( isset($this->ticks_label[$i*$m]) ) {
    4064                     $label=$this->ticks_label[$i*$m];
    4065                 }
    4066                 else {
    4067                     if( $aAbsLabel ) {
    4068                         $label=abs($this->scale->ticks->maj_ticks_label[$i]);
    4069                     }
    4070                     else {
    4071                         $label=$this->scale->ticks->maj_ticks_label[$i];
    4072                     }
    4073 
    4074                     // We number the scale from 1 and not from 0 so increase by one
    4075                     if( $this->scale->textscale &&
    4076                         $this->scale->ticks->label_formfunc == '' &&
    4077                         ! $this->scale->ticks->HaveManualLabels() ) {
    4078 
    4079                         ++$label;
    4080                        
    4081                     }
    4082                 }
    4083 
    4084                 if( $this->scale->type == "x" ) {
    4085                     if( $this->labelPos == SIDE_DOWN ) {
    4086                         if( $this->label_angle==0 || $this->label_angle==90 ) {
    4087                             if( $this->label_halign=='' && $this->label_valign=='') {
    4088                                 $this->img->SetTextAlign('center','top');
    4089                             }
    4090                             else {
    4091                                 $this->img->SetTextAlign($this->label_halign,$this->label_valign);
    4092                             }
    4093 
    4094                         }
    4095                         else {
    4096                             if( $this->label_halign=='' && $this->label_valign=='') {
    4097                                 $this->img->SetTextAlign("right","top");
    4098                             }
    4099                             else {
    4100                                 $this->img->SetTextAlign($this->label_halign,$this->label_valign);
    4101                             }
    4102                         }
    4103                         $this->img->StrokeText($tpos,$aPos+$this->tick_label_margin,$label,
    4104                         $this->label_angle,$this->label_para_align);
    4105                     }
    4106                     else {
    4107                         if( $this->label_angle==0 || $this->label_angle==90 ) {
    4108                             if( $this->label_halign=='' && $this->label_valign=='') {
    4109                                 $this->img->SetTextAlign("center","bottom");
    4110                             }
    4111                             else {
    4112                                 $this->img->SetTextAlign($this->label_halign,$this->label_valign);
    4113                             }
    4114                         }
    4115                         else {
    4116                             if( $this->label_halign=='' && $this->label_valign=='') {
    4117                                 $this->img->SetTextAlign("right","bottom");
    4118                             }
    4119                             else {
    4120                                 $this->img->SetTextAlign($this->label_halign,$this->label_valign);
    4121                             }
    4122                         }
    4123                         $this->img->StrokeText($tpos,$aPos-$this->tick_label_margin-1,$label,
    4124                         $this->label_angle,$this->label_para_align);
    4125                     }
    4126                 }
    4127                 else {
    4128                     // scale->type == "y"
    4129                     //if( $this->label_angle!=0 )
    4130                     //JpGraphError::Raise(" Labels at an angle are not supported on Y-axis");
    4131                     if( $this->labelPos == SIDE_LEFT ) { // To the left of y-axis
    4132                         if( $this->label_halign=='' && $this->label_valign=='') {
    4133                             $this->img->SetTextAlign("right","center");
    4134                         }
    4135                         else {
    4136                             $this->img->SetTextAlign($this->label_halign,$this->label_valign);
    4137                         }
    4138                         $this->img->StrokeText($aPos-$this->tick_label_margin,$tpos,$label,$this->label_angle,$this->label_para_align);
    4139                     }
    4140                     else { // To the right of the y-axis
    4141                         if( $this->label_halign=='' && $this->label_valign=='') {
    4142                             $this->img->SetTextAlign("left","center");
    4143                         }
    4144                         else {
    4145                             $this->img->SetTextAlign($this->label_halign,$this->label_valign);
    4146                         }
    4147                         $this->img->StrokeText($aPos+$this->tick_label_margin,$tpos,$label,$this->label_angle,$this->label_para_align);
    4148                     }
    4149                 }
    4150             }
    4151             ++$i;
    4152         }
    4153     }
     3680        $this->img->SetColor($this->label_color);
     3681        $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
     3682        $yoff=$this->img->GetFontHeight()/2;
     3683
     3684        // Only draw labels at major tick marks
     3685        $nbr = count($this->scale->ticks->maj_ticks_label);
     3686
     3687        // We have the option to not-display the very first mark
     3688        // (Usefull when the first label might interfere with another
     3689        // axis.)
     3690        $i = $this->show_first_label ? 0 : 1 ;
     3691        if( !$this->show_last_label ) --$nbr;
     3692        // Now run through all labels making sure we don't overshoot the end
     3693        // of the scale.       
     3694        $ncolor=0;
     3695        if( isset($this->ticks_label_colors) )
     3696            $ncolor=count($this->ticks_label_colors);
     3697        while( $i<$nbr ) {
     3698            // $tpos holds the absolute text position for the label
     3699            $tpos=$this->scale->ticks->maj_ticklabels_pos[$i];
     3700
     3701            // Note. the $limit is only used for the x axis since we
     3702            // might otherwise overshoot if the scale has been centered
     3703            // This is due to us "loosing" the last tick mark if we center.
     3704            if( $this->scale->type=="x" && $tpos > $this->img->width-$this->img->right_margin+1 ) {
     3705                return;
     3706            }
     3707            // we only draw every $label_step label
     3708            if( ($i % $this->label_step)==0 ) {
     3709
     3710                // Set specific label color if specified
     3711                if( $ncolor > 0 )
     3712                    $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]);
     3713               
     3714                // If the label has been specified use that and in other case
     3715                // just label the mark with the actual scale value
     3716                $m=$this->scale->ticks->GetMajor();
     3717                               
     3718                // ticks_label has an entry for each data point and is the array
     3719                // that holds the labels set by the user. If the user hasn't
     3720                // specified any values we use whats in the automatically asigned
     3721                // labels in the maj_ticks_label
     3722                if( isset($this->ticks_label[$i*$m]) )
     3723                    $label=$this->ticks_label[$i*$m];
     3724                else {
     3725                    if( $aAbsLabel )
     3726                        $label=abs($this->scale->ticks->maj_ticks_label[$i]);
     3727                    else
     3728                        $label=$this->scale->ticks->maj_ticks_label[$i];
     3729                    if( $this->scale->textscale && $this->scale->ticks->label_formfunc == '' ) {
     3730                        ++$label;
     3731                    }
     3732                }
     3733                                       
     3734                if( $this->scale->type == "x" ) {
     3735                    if( $this->labelPos == SIDE_DOWN ) {
     3736                        if( $this->label_angle==0 || $this->label_angle==90 ) {
     3737                            if( $this->label_halign=='' && $this->label_valign=='')
     3738                                $this->img->SetTextAlign('center','top');
     3739                            else
     3740                                $this->img->SetTextAlign($this->label_halign,$this->label_valign);
     3741                           
     3742                        }
     3743                        else {
     3744                            if( $this->label_halign=='' && $this->label_valign=='')
     3745                                $this->img->SetTextAlign("right","top");
     3746                            else
     3747                                $this->img->SetTextAlign($this->label_halign,$this->label_valign);
     3748                        }
     3749                        $this->img->StrokeText($tpos,$aPos+$this->tick_label_margin+1,$label,
     3750                                               $this->label_angle,$this->label_para_align);
     3751                    }
     3752                    else {
     3753                        if( $this->label_angle==0 || $this->label_angle==90 ) {
     3754                            if( $this->label_halign=='' && $this->label_valign=='')
     3755                                $this->img->SetTextAlign("center","bottom");
     3756                            else
     3757                                $this->img->SetTextAlign($this->label_halign,$this->label_valign);
     3758                        }
     3759                        else {
     3760                            if( $this->label_halign=='' && $this->label_valign=='')
     3761                                $this->img->SetTextAlign("right","bottom");
     3762                            else
     3763                                $this->img->SetTextAlign($this->label_halign,$this->label_valign);
     3764                        }
     3765                        $this->img->StrokeText($tpos,$aPos-$this->tick_label_margin-1,$label,
     3766                                               $this->label_angle,$this->label_para_align);
     3767                    }
     3768                }
     3769                else {
     3770                    // scale->type == "y"
     3771                    //if( $this->label_angle!=0 )
     3772                    //JpGraphError::Raise(" Labels at an angle are not supported on Y-axis");
     3773                    if( $this->labelPos == SIDE_LEFT ) { // To the left of y-axis                                       
     3774                        if( $this->label_halign=='' && $this->label_valign=='')
     3775                            $this->img->SetTextAlign("right","center");
     3776                        else
     3777                            $this->img->SetTextAlign($this->label_halign,$this->label_valign);
     3778                        $this->img->StrokeText($aPos-$this->tick_label_margin,$tpos,$label,$this->label_angle,$this->label_para_align);
     3779                    }
     3780                    else { // To the right of the y-axis
     3781                        if( $this->label_halign=='' && $this->label_valign=='')
     3782                            $this->img->SetTextAlign("left","center");
     3783                        else
     3784                            $this->img->SetTextAlign($this->label_halign,$this->label_valign);
     3785                        $this->img->StrokeText($aPos+$this->tick_label_margin,$tpos,$label,$this->label_angle,$this->label_para_align);
     3786                    }
     3787                }
     3788            }
     3789            ++$i;       
     3790        }                                                               
     3791    }                       
    41543792
    41553793}
     
    41673805    public $direction=1; // Should ticks be in(=1) the plot area or outside (=-1)
    41683806    public $supress_last=false,$supress_tickmarks=false,$supress_minor_tickmarks=false;
    4169     public $maj_ticks_pos = array(), $maj_ticklabels_pos = array(),
    4170            $ticks_pos = array(), $maj_ticks_label = array();
     3807    public $maj_ticks_pos = array(), $maj_ticklabels_pos = array(), 
     3808           $ticks_pos = array(), $maj_ticks_label = array();
    41713809    public $precision;
    41723810
     
    41753813    protected $is_set=false;
    41763814    protected $supress_zerolabel=false,$supress_first=false;
    4177     protected $mincolor='',$majcolor='';
     3815    protected $mincolor="",$majcolor="";
    41783816    protected $weight=1;
    41793817    protected $label_usedateformat=FALSE;
    41803818
    4181     function __construct($aScale) {
    4182         $this->scale=$aScale;
    4183         $this->precision = -1;
    4184     }
    4185 
     3819//---------------
     3820// CONSTRUCTOR
     3821    function Ticks($aScale) {
     3822        $this->scale=$aScale;
     3823        $this->precision = -1;
     3824    }
     3825
     3826//---------------
     3827// PUBLIC METHODS       
    41863828    // Set format string for automatic labels
    41873829    function SetLabelFormat($aFormatString,$aDate=FALSE) {
    4188         $this->label_formatstr=$aFormatString;
    4189         $this->label_usedateformat=$aDate;
    4190     }
    4191 
     3830        $this->label_formatstr=$aFormatString;
     3831        $this->label_usedateformat=$aDate;
     3832    }
     3833       
    41923834    function SetLabelDateFormat($aFormatString) {
    4193         $this->label_dateformatstr=$aFormatString;
    4194     }
    4195 
     3835        $this->label_dateformatstr=$aFormatString;
     3836    }
     3837       
    41963838    function SetFormatCallback($aCallbackFuncName) {
    4197         $this->label_formfunc = $aCallbackFuncName;
    4198     }
    4199 
     3839        $this->label_formfunc = $aCallbackFuncName;
     3840    }
     3841       
    42003842    // Don't display the first zero label
    42013843    function SupressZeroLabel($aFlag=true) {
    4202         $this->supress_zerolabel=$aFlag;
    4203     }
    4204 
     3844        $this->supress_zerolabel=$aFlag;
     3845    }
     3846       
    42053847    // Don't display minor tick marks
    42063848    function SupressMinorTickMarks($aHide=true) {
    4207         $this->supress_minor_tickmarks=$aHide;
    4208     }
    4209 
     3849        $this->supress_minor_tickmarks=$aHide;
     3850    }
     3851       
    42103852    // Don't display major tick marks
    42113853    function SupressTickMarks($aHide=true) {
    4212         $this->supress_tickmarks=$aHide;
    4213     }
    4214 
     3854        $this->supress_tickmarks=$aHide;
     3855    }
     3856       
    42153857    // Hide the first tick mark
    42163858    function SupressFirst($aHide=true) {
    4217         $this->supress_first=$aHide;
    4218     }
    4219 
     3859        $this->supress_first=$aHide;
     3860    }
     3861       
    42203862    // Hide the last tick mark
    42213863    function SupressLast($aHide=true) {
    4222         $this->supress_last=$aHide;
     3864        $this->supress_last=$aHide;
    42233865    }
    42243866
    42253867    // Size (in pixels) of minor tick marks
    42263868    function GetMinTickAbsSize() {
    4227         return $this->minor_abs_size;
    4228     }
    4229 
     3869        return $this->minor_abs_size;
     3870    }
     3871       
    42303872    // Size (in pixels) of major tick marks
    42313873    function GetMajTickAbsSize() {
    4232         return $this->major_abs_size;
    4233     }
    4234 
     3874        return $this->major_abs_size;           
     3875    }
     3876       
    42353877    function SetSize($aMajSize,$aMinSize=3) {
    4236         $this->major_abs_size = $aMajSize;
    4237         $this->minor_abs_size = $aMinSize;
     3878        $this->major_abs_size = $aMajSize;             
     3879        $this->minor_abs_size = $aMinSize;             
    42383880    }
    42393881
    42403882    // Have the ticks been specified
    42413883    function IsSpecified() {
    4242         return $this->is_set;
     3884        return $this->is_set;
     3885    }
     3886               
     3887    // Specify number of decimals in automatic labels
     3888    // Deprecated from 1.4. Use SetFormatString() instead
     3889    function SetPrecision($aPrecision) {       
     3890        if( ERR_DEPRECATED )
     3891            JpGraphError::RaiseL(25063);//('Ticks::SetPrecision() is deprecated. Use Ticks::SetLabelFormat() (or Ticks::SetFormatCallback()) instead');
     3892        $this->precision=$aPrecision;
    42433893    }
    42443894
    42453895    function SetSide($aSide) {
    4246         $this->direction=$aSide;
    4247     }
    4248 
     3896        $this->direction=$aSide;
     3897    }
     3898       
    42493899    // Which side of the axis should the ticks be on
    42503900    function SetDirection($aSide=SIDE_RIGHT) {
    4251         $this->direction=$aSide;
    4252     }
    4253 
     3901        $this->direction=$aSide;
     3902    }
     3903       
    42543904    // Set colors for major and minor tick marks
    4255     function SetMarkColor($aMajorColor,$aMinorColor='') {
    4256         $this->SetColor($aMajorColor,$aMinorColor);
    4257     }
    4258 
    4259     function SetColor($aMajorColor,$aMinorColor='') {
    4260         $this->majcolor=$aMajorColor;
    4261 
    4262         // If not specified use same as major
    4263         if( $aMinorColor == '' ) {
    4264             $this->mincolor=$aMajorColor;
    4265         }
    4266         else {
    4267             $this->mincolor=$aMinorColor;
    4268         }
    4269     }
    4270 
     3905    function SetMarkColor($aMajorColor,$aMinorColor="") {
     3906        $this->SetColor($aMajorColor,$aMinorColor);
     3907    }
     3908   
     3909    function SetColor($aMajorColor,$aMinorColor="") {
     3910        $this->majcolor=$aMajorColor;
     3911               
     3912        // If not specified use same as major
     3913        if( $aMinorColor=="" )
     3914            $this->mincolor=$aMajorColor;
     3915        else
     3916            $this->mincolor=$aMinorColor;
     3917    }
     3918       
    42713919    function SetWeight($aWeight) {
    4272         $this->weight=$aWeight;
    4273     }
    4274 
     3920        $this->weight=$aWeight;
     3921    }
     3922       
    42753923} // Class
    42763924
     
    42883936    private $iAdjustForDST = false; // If a date falls within the DST period add one hour to the diaplyed time
    42893937
    4290     function __construct() {
    4291         $this->precision = -1;
    4292     }
    4293 
     3938//---------------
     3939// CONSTRUCTOR
     3940    function LinearTicks() {
     3941        $this->precision = -1;
     3942    }
     3943
     3944//---------------
     3945// PUBLIC METHODS       
     3946       
     3947       
    42943948    // Return major step size in world coordinates
    42953949    function GetMajor() {
    4296         return $this->major_step;
    4297     }
    4298 
     3950        return $this->major_step;
     3951    }
     3952       
    42993953    // Return minor step size in world coordinates
    43003954    function GetMinor() {
    4301         return $this->minor_step;
    4302     }
    4303 
     3955        return $this->minor_step;
     3956    }
     3957       
    43043958    // Set Minor and Major ticks (in world coordinates)
    43053959    function Set($aMajStep,$aMinStep=false) {
    4306         if( $aMinStep==false ) {
    4307             $aMinStep=$aMajStep;
    4308         }
    4309 
    4310         if( $aMajStep <= 0 || $aMinStep <= 0 ) {
    4311             JpGraphError::RaiseL(25064);
    4312             //(" Minor or major step size is 0. Check that you haven't got an accidental SetTextTicks(0) in your code. If this is not the case you might have stumbled upon a bug in JpGraph. Please report this and if possible include the data that caused the problem.");
    4313         }
    4314 
    4315         $this->major_step=$aMajStep;
    4316         $this->minor_step=$aMinStep;
    4317         $this->is_set = true;
     3960        if( $aMinStep==false )
     3961            $aMinStep=$aMajStep;
     3962       
     3963        if( $aMajStep <= 0 || $aMinStep <= 0 ) {
     3964            JpGraphError::RaiseL(25064);
     3965//(" Minor or major step size is 0. Check that you haven't got an accidental SetTextTicks(0) in your code. If this is not the case you might have stumbled upon a bug in JpGraph. Please report this and if possible include the data that caused the problem.");
     3966        }
     3967               
     3968        $this->major_step=$aMajStep;
     3969        $this->minor_step=$aMinStep;
     3970        $this->is_set = true;
    43183971    }
    43193972
    43203973    function SetMajTickPositions($aMajPos,$aLabels=NULL) {
    4321         $this->SetTickPositions($aMajPos,NULL,$aLabels);
     3974        $this->SetTickPositions($aMajPos,NULL,$aLabels);
    43223975    }
    43233976
    43243977    function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) {
    4325         if( !is_array($aMajPos) || ($aMinPos!==NULL && !is_array($aMinPos)) ) {
    4326             JpGraphError::RaiseL(25065);//('Tick positions must be specifued as an array()');
    4327             return;
    4328         }
    4329         $n=count($aMajPos);
    4330         if( is_array($aLabels) && (count($aLabels) != $n) ) {
    4331             JpGraphError::RaiseL(25066);//('When manually specifying tick positions and labels the number of labels must be the same as the number of specified ticks.');
    4332         }
    4333         $this->iManualTickPos = $aMajPos;
    4334         $this->iManualMinTickPos = $aMinPos;
    4335         $this->iManualTickLabels = $aLabels;
    4336     }
    4337 
    4338     function HaveManualLabels() {
    4339         return is_array($this->iManualTickLabels) ? count($this->iManualTickLabels) > 0 : false;
    4340     }
    4341 
    4342     // Specify all the tick positions manually and possible also the exact labels
    4343     function _doManualTickPos($aScale) {
    4344         $n=count($this->iManualTickPos);
    4345         $m= is_array($this->iManualMinTickPos) ? count($this->iManualMinTickPos) : 0;
    4346         $doLbl= is_array($this->iManualTickLabels) ? count($this->iManualTickLabels) > 0 : false;
    4347 
    4348         $this->maj_ticks_pos = array();
    4349         $this->maj_ticklabels_pos = array();
    4350         $this->ticks_pos = array();
    4351 
    4352         // Now loop through the supplied positions and translate them to screen coordinates
    4353         // and store them in the maj_label_positions
    4354         $minScale = $aScale->scale[0];
    4355         $maxScale = $aScale->scale[1];
    4356         $j=0;
    4357         for($i=0; $i < $n ; ++$i ) {
    4358             // First make sure that the first tick is not lower than the lower scale value
    4359             if( !isset($this->iManualTickPos[$i]) || $this->iManualTickPos[$i] < $minScale  || $this->iManualTickPos[$i] > $maxScale) {
    4360                 continue;
    4361             }
    4362 
    4363             $this->maj_ticks_pos[$j] = $aScale->Translate($this->iManualTickPos[$i]);
    4364             $this->maj_ticklabels_pos[$j] = $this->maj_ticks_pos[$j];
    4365 
    4366             // Set the minor tick marks the same as major if not specified
    4367             if( $m <= 0 ) {
    4368                 $this->ticks_pos[$j] = $this->maj_ticks_pos[$j];
    4369             }
    4370             if( $doLbl ) {
    4371                 $this->maj_ticks_label[$j] = $this->iManualTickLabels[$i];
    4372             }
    4373             else {
    4374                 $this->maj_ticks_label[$j]=$this->_doLabelFormat($this->iManualTickPos[$i],$i,$n);
    4375             }
    4376             ++$j;
    4377         }
    4378 
    4379         // Some sanity check
    4380         if( count($this->maj_ticks_pos) < 2 ) {
    4381             JpGraphError::RaiseL(25067);//('Your manually specified scale and ticks is not correct. The scale seems to be too small to hold any of the specified tickl marks.');
    4382         }
    4383 
    4384         // Setup the minor tick marks
    4385         $j=0;
    4386         for($i=0; $i < $m; ++$i ) {
    4387             if(  empty($this->iManualMinTickPos[$i]) || $this->iManualMinTickPos[$i] < $minScale  || $this->iManualMinTickPos[$i] > $maxScale) {
    4388                 continue;
    4389             }
    4390             $this->ticks_pos[$j] = $aScale->Translate($this->iManualMinTickPos[$i]);
    4391             ++$j;
    4392         }
     3978        if( !is_array($aMajPos) || ($aMinPos!==NULL && !is_array($aMinPos)) ) {
     3979            JpGraphError::RaiseL(25065);//('Tick positions must be specifued as an array()');
     3980            return;
     3981        }
     3982        $n=count($aMajPos);
     3983        if( is_array($aLabels) && (count($aLabels) != $n) ) {
     3984            JpGraphError::RaiseL(25066);//('When manually specifying tick positions and labels the number of labels must be the same as the number of specified ticks.');
     3985            return;
     3986        }
     3987        $this->iManualTickPos = $aMajPos;
     3988        $this->iManualMinTickPos = $aMinPos;
     3989        $this->iManualTickLabels = $aLabels;
     3990    }
     3991
     3992    // Specify all the tick positions manually and possible also the exact labels
     3993    function _doManualTickPos($aScale) {
     3994        $n=count($this->iManualTickPos);
     3995        $m=count($this->iManualMinTickPos);
     3996        $doLbl=count($this->iManualTickLabels) > 0;
     3997
     3998        $this->maj_ticks_pos = array();
     3999        $this->maj_ticklabels_pos = array();
     4000        $this->ticks_pos = array();
     4001
     4002        // Now loop through the supplied positions and translate them to screen coordinates
     4003        // and store them in the maj_label_positions
     4004        $minScale = $aScale->scale[0];
     4005        $maxScale = $aScale->scale[1];
     4006        $j=0;
     4007        for($i=0; $i < $n ; ++$i ) {
     4008            // First make sure that the first tick is not lower than the lower scale value
     4009            if( !isset($this->iManualTickPos[$i])  ||
     4010                $this->iManualTickPos[$i] < $minScale  || $this->iManualTickPos[$i] > $maxScale) {
     4011                continue;
     4012            }
     4013
     4014
     4015            $this->maj_ticks_pos[$j] = $aScale->Translate($this->iManualTickPos[$i]);
     4016            $this->maj_ticklabels_pos[$j] = $this->maj_ticks_pos[$j];   
     4017
     4018            // Set the minor tick marks the same as major if not specified
     4019            if( $m <= 0 ) {
     4020                $this->ticks_pos[$j] = $this->maj_ticks_pos[$j];
     4021            }
     4022
     4023            if( $doLbl ) {
     4024                $this->maj_ticks_label[$j] = $this->iManualTickLabels[$i];
     4025            }
     4026            else {
     4027                $this->maj_ticks_label[$j]=$this->_doLabelFormat($this->iManualTickPos[$i],$i,$n);
     4028            }
     4029            ++$j;
     4030        }
     4031
     4032        // Some sanity check
     4033        if( count($this->maj_ticks_pos) < 2 ) {
     4034            JpGraphError::RaiseL(25067);//('Your manually specified scale and ticks is not correct. The scale seems to be too small to hold any of the specified tickl marks.');
     4035        }
     4036
     4037        // Setup the minor tick marks
     4038        $j=0;
     4039        for($i=0; $i < $m; ++$i ) {
     4040            if(  empty($this->iManualMinTickPos[$i]) ||
     4041                 $this->iManualMinTickPos[$i] < $minScale  || $this->iManualMinTickPos[$i] > $maxScale)
     4042                continue;
     4043            $this->ticks_pos[$j] = $aScale->Translate($this->iManualMinTickPos[$i]);
     4044            ++$j;
     4045        }
    43934046    }
    43944047
    43954048    function _doAutoTickPos($aScale) {
    4396         $maj_step_abs = $aScale->scale_factor*$this->major_step;
    4397         $min_step_abs = $aScale->scale_factor*$this->minor_step;
    4398 
    4399         if( $min_step_abs==0 || $maj_step_abs==0 ) {
    4400             JpGraphError::RaiseL(25068);//("A plot has an illegal scale. This could for example be that you are trying to use text autoscaling to draw a line plot with only one point or that the plot area is too small. It could also be that no input data value is numeric (perhaps only '-' or 'x')");
    4401         }
    4402         // We need to make this an int since comparing it below
    4403         // with the result from round() can give wrong result, such that
    4404         // (40 < 40) == TRUE !!!
    4405         $limit = (int)$aScale->scale_abs[1];
    4406 
    4407         if( $aScale->textscale ) {
    4408             // This can only be true for a X-scale (horizontal)
    4409             // Define ticks for a text scale. This is slightly different from a
    4410             // normal linear type of scale since the position might be adjusted
    4411             // and the labels start at on
    4412             $label = (float)$aScale->GetMinVal()+$this->text_label_start+$this->label_offset;
    4413             $start_abs=$aScale->scale_factor*$this->text_label_start;
    4414             $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1;
    4415 
    4416             $x = $aScale->scale_abs[0]+$start_abs+$this->xlabel_offset*$min_step_abs;
    4417             for( $i=0; $label <= $aScale->GetMaxVal()+$this->label_offset; ++$i ) {
    4418                 // Apply format to label
    4419                 $this->maj_ticks_label[$i]=$this->_doLabelFormat($label,$i,$nbrmajticks);
    4420                 $label+=$this->major_step;
    4421 
    4422                 // The x-position of the tick marks can be different from the labels.
    4423                 // Note that we record the tick position (not the label) so that the grid
    4424                 // happen upon tick marks and not labels.
    4425                 $xtick=$aScale->scale_abs[0]+$start_abs+$this->xtick_offset*$min_step_abs+$i*$maj_step_abs;
    4426                 $this->maj_ticks_pos[$i]=$xtick;
    4427                 $this->maj_ticklabels_pos[$i] = round($x);
    4428                 $x += $maj_step_abs;
    4429             }
    4430         }
    4431         else {
    4432             $label = $aScale->GetMinVal();
    4433             $abs_pos = $aScale->scale_abs[0];
    4434             $j=0; $i=0;
    4435             $step = round($maj_step_abs/$min_step_abs);
    4436             if( $aScale->type == "x" ) {
    4437                 // For a normal linear type of scale the major ticks will always be multiples
    4438                 // of the minor ticks. In order to avoid any rounding issues the major ticks are
    4439                 // defined as every "step" minor ticks and not calculated separately
    4440                 $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1;
    4441                 while( round($abs_pos) <= $limit ) {
    4442                     $this->ticks_pos[] = round($abs_pos);
    4443                     $this->ticks_label[] = $label;
    4444                     if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks ) {
    4445                         $this->maj_ticks_pos[$j] = round($abs_pos);
    4446                         $this->maj_ticklabels_pos[$j] = round($abs_pos);
    4447                         $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks);
    4448                         ++$j;
    4449                     }
    4450                     ++$i;
    4451                     $abs_pos += $min_step_abs;
    4452                     $label+=$this->minor_step;
    4453                 }
    4454             }
    4455             elseif( $aScale->type == "y" ) {
    4456                 //@todo  s=2:20,12  s=1:50,6  $this->major_step:$nbr
    4457                 // abs_point,limit s=1:270,80 s=2:540,160
    4458              // $this->major_step = 50;
    4459                 $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal())/$this->major_step)+1;
    4460 //                $step = 5;
    4461                 while( round($abs_pos) >= $limit ) {
    4462                     $this->ticks_pos[$i] = round($abs_pos);
    4463                     $this->ticks_label[$i]=$label;
    4464                     if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks) {
    4465                         $this->maj_ticks_pos[$j] = round($abs_pos);
    4466                         $this->maj_ticklabels_pos[$j] = round($abs_pos);
    4467                         $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks);
    4468                         ++$j;
    4469                     }
    4470                     ++$i;
    4471                     $abs_pos += $min_step_abs;
    4472                     $label += $this->minor_step;
    4473                 }
    4474             }
    4475         }
     4049        $maj_step_abs = $aScale->scale_factor*$this->major_step;               
     4050        $min_step_abs = $aScale->scale_factor*$this->minor_step;               
     4051
     4052        if( $min_step_abs==0 || $maj_step_abs==0 ) {
     4053            JpGraphError::RaiseL(25068);//("A plot has an illegal scale. This could for example be that you are trying to use text autoscaling to draw a line plot with only one point or that the plot area is too small. It could also be that no input data value is numeric (perhaps only '-' or 'x')");
     4054        }
     4055        // We need to make this an int since comparing it below
     4056        // with the result from round() can give wrong result, such that
     4057        // (40 < 40) == TRUE !!!
     4058        $limit = (int)$aScale->scale_abs[1];   
     4059
     4060        if( $aScale->textscale ) {
     4061            // This can only be true for a X-scale (horizontal)
     4062            // Define ticks for a text scale. This is slightly different from a
     4063            // normal linear type of scale since the position might be adjusted
     4064            // and the labels start at on
     4065            $label = (float)$aScale->GetMinVal()+$this->text_label_start+$this->label_offset;   
     4066            $start_abs=$aScale->scale_factor*$this->text_label_start;
     4067            $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1;       
     4068
     4069            $x = $aScale->scale_abs[0]+$start_abs+$this->xlabel_offset*$min_step_abs;   
     4070            for( $i=0; $label <= $aScale->GetMaxVal()+$this->label_offset; ++$i ) {
     4071                // Apply format to label
     4072                $this->maj_ticks_label[$i]=$this->_doLabelFormat($label,$i,$nbrmajticks);
     4073                $label+=$this->major_step;
     4074
     4075                // The x-position of the tick marks can be different from the labels.
     4076                // Note that we record the tick position (not the label) so that the grid
     4077                // happen upon tick marks and not labels.
     4078                $xtick=$aScale->scale_abs[0]+$start_abs+$this->xtick_offset*$min_step_abs+$i*$maj_step_abs;
     4079                $this->maj_ticks_pos[$i]=$xtick;
     4080                $this->maj_ticklabels_pos[$i] = round($x);                             
     4081                $x += $maj_step_abs;
     4082            }
     4083        }
     4084        else {
     4085            $label = $aScale->GetMinVal();     
     4086            $abs_pos = $aScale->scale_abs[0];
     4087            $j=0; $i=0;
     4088            $step = round($maj_step_abs/$min_step_abs);
     4089            if( $aScale->type == "x" ) {
     4090                // For a normal linear type of scale the major ticks will always be multiples
     4091                // of the minor ticks. In order to avoid any rounding issues the major ticks are
     4092                // defined as every "step" minor ticks and not calculated separately
     4093                $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1;
     4094                while( round($abs_pos) <= $limit ) {
     4095                    $this->ticks_pos[] = round($abs_pos);
     4096                    $this->ticks_label[] = $label;
     4097                    if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks ) {
     4098                        $this->maj_ticks_pos[$j] = round($abs_pos);
     4099                        $this->maj_ticklabels_pos[$j] = round($abs_pos);
     4100                        $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks);
     4101                        ++$j;
     4102                    }
     4103                    ++$i;
     4104                    $abs_pos += $min_step_abs;
     4105                    $label+=$this->minor_step;
     4106                }
     4107            }
     4108            elseif( $aScale->type == "y" ) {
     4109                $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal())/$this->major_step)+1;
     4110                while( round($abs_pos) >= $limit ) {
     4111                    $this->ticks_pos[$i] = round($abs_pos);
     4112                    $this->ticks_label[$i]=$label;
     4113                    if( $step== 0 || $i % $step == 0 && $j < $nbrmajticks) {
     4114                        $this->maj_ticks_pos[$j] = round($abs_pos);
     4115                        $this->maj_ticklabels_pos[$j] = round($abs_pos);
     4116                        $this->maj_ticks_label[$j]=$this->_doLabelFormat($label,$j,$nbrmajticks);
     4117                        ++$j;
     4118                    }
     4119                    ++$i;
     4120                    $abs_pos += $min_step_abs;
     4121                    $label += $this->minor_step;
     4122                }       
     4123            }
     4124        }       
    44764125    }
    44774126
    44784127    function AdjustForDST($aFlg=true) {
    4479         $this->iAdjustForDST = $aFlg;
     4128        $this->iAdjustForDST = $aFlg;
    44804129    }
    44814130
     
    44834132    function _doLabelFormat($aVal,$aIdx,$aNbrTicks) {
    44844133
    4485         // If precision hasn't been specified set it to a sensible value
    4486         if( $this->precision==-1 ) {
    4487             $t = log10($this->minor_step);
    4488             if( $t > 0 || $t === 0.0) {
    4489                 $precision = 0;
    4490             }
    4491             else {
    4492                 $precision = -floor($t);
    4493             }
    4494         }
    4495         else {
    4496             $precision = $this->precision;
    4497         }
    4498 
    4499         if( $this->label_formfunc != '' ) {
    4500             $f=$this->label_formfunc;
    4501             if( $this->label_formatstr == '' ) {
    4502                 $l = call_user_func($f,$aVal);
    4503             }
    4504             else {
    4505                 $l = sprintf($this->label_formatstr, call_user_func($f,$aVal));
    4506             }
    4507         }
    4508         elseif( $this->label_formatstr != '' || $this->label_dateformatstr != '' ) {
    4509             if( $this->label_usedateformat ) {
    4510                 // Adjust the value to take daylight savings into account
    4511                 if (date("I",$aVal)==1 && $this->iAdjustForDST ) {
    4512                     // DST
    4513                     $aVal+=3600;
    4514                 }
    4515 
    4516                 $l = date($this->label_formatstr,$aVal);
    4517                 if( $this->label_formatstr == 'W' ) {
    4518                     // If we use week formatting then add a single 'w' in front of the
    4519                     // week number to differentiate it from dates
    4520                     $l = 'w'.$l;
    4521                 }
    4522             }
    4523             else {
    4524                 if( $this->label_dateformatstr !== '' ) {
    4525                     // Adjust the value to take daylight savings into account
    4526                     if (date("I",$aVal)==1 && $this->iAdjustForDST ) {
    4527                         // DST
    4528                         $aVal+=3600;
    4529                     }
    4530 
    4531                     $l = date($this->label_dateformatstr,$aVal);
    4532                     if( $this->label_formatstr == 'W' ) {
    4533                         // If we use week formatting then add a single 'w' in front of the
    4534                         // week number to differentiate it from dates
    4535                         $l = 'w'.$l;
    4536                     }
    4537                 }
    4538                 else {
    4539                     $l = sprintf($this->label_formatstr,$aVal);
    4540                 }
    4541             }
    4542         }
    4543         else {
    4544             $l = sprintf('%01.'.$precision.'f',round($aVal,$precision));
    4545         }
    4546 
    4547         if( ($this->supress_zerolabel && $l==0) ||  ($this->supress_first && $aIdx==0) || ($this->supress_last  && $aIdx==$aNbrTicks-1) ) {
    4548             $l='';
    4549         }
    4550         return $l;
     4134        // If precision hasn't been specified set it to a sensible value
     4135        if( $this->precision==-1 ) {
     4136            $t = log10($this->minor_step);
     4137            if( $t > 0 )
     4138                $precision = 0;
     4139            else
     4140                $precision = -floor($t);
     4141        }
     4142        else
     4143            $precision = $this->precision;
     4144
     4145        if( $this->label_formfunc != '' ) {
     4146            $f=$this->label_formfunc;
     4147            $l = call_user_func($f,$aVal);
     4148        }       
     4149        elseif( $this->label_formatstr != '' || $this->label_dateformatstr != '' ) {
     4150            if( $this->label_usedateformat ) {
     4151                // Adjust the value to take daylight savings into account
     4152                if (date("I",$aVal)==1 && $this->iAdjustForDST ) // DST
     4153                    $aVal+=3600;
     4154
     4155                $l = date($this->label_formatstr,$aVal);
     4156                if( $this->label_formatstr == 'W' ) {
     4157                    // If we use week formatting then add a single 'w' in front of the
     4158                    // week number to differentiate it from dates
     4159                    $l = 'w'.$l;
     4160                }
     4161            }
     4162            else {
     4163                if( $this->label_dateformatstr !== '' ) {
     4164                    // Adjust the value to take daylight savings into account
     4165                    if (date("I",$aVal)==1 && $this->iAdjustForDST ) // DST
     4166                        $aVal+=3600;
     4167
     4168                    $l = date($this->label_dateformatstr,$aVal);
     4169                    if( $this->label_formatstr == 'W' ) {
     4170                        // If we use week formatting then add a single 'w' in front of the
     4171                        // week number to differentiate it from dates
     4172                        $l = 'w'.$l;
     4173                    }
     4174                }
     4175                else
     4176                    $l = sprintf($this->label_formatstr,$aVal);
     4177            }
     4178        }
     4179        else {
     4180            $l = sprintf('%01.'.$precision.'f',round($aVal,$precision));
     4181        }
     4182       
     4183        if( ($this->supress_zerolabel && $l==0) ||  ($this->supress_first && $aIdx==0) ||
     4184            ($this->supress_last  && $aIdx==$aNbrTicks-1) ) {
     4185            $l='';
     4186        }
     4187        return $l;
    45514188    }
    45524189
    45534190    // Stroke ticks on either X or Y axis
    45544191    function _StrokeTicks($aImg,$aScale,$aPos) {
    4555         $hor = $aScale->type == 'x';
    4556         $aImg->SetLineWeight($this->weight);
    4557 
    4558         // We need to make this an int since comparing it below
    4559         // with the result from round() can give wrong result, such that
    4560         // (40 < 40) == TRUE !!!
    4561         $limit = (int)$aScale->scale_abs[1];
    4562 
    4563         // A text scale doesn't have any minor ticks
    4564         if( !$aScale->textscale ) {
    4565             // Stroke minor ticks
    4566             $yu = $aPos - $this->direction*$this->GetMinTickAbsSize();
    4567             $xr = $aPos + $this->direction*$this->GetMinTickAbsSize();
    4568             $n = count($this->ticks_pos);
    4569             for($i=0; $i < $n; ++$i ) {
    4570                 if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
    4571                     if( $this->mincolor != '') {
    4572                         $aImg->PushColor($this->mincolor);
    4573                     }
    4574                     if( $hor ) {
    4575                         //if( $this->ticks_pos[$i] <= $limit )
    4576                         $aImg->Line($this->ticks_pos[$i],$aPos,$this->ticks_pos[$i],$yu);
    4577                     }
    4578                     else {
    4579                         //if( $this->ticks_pos[$i] >= $limit )
    4580                         $aImg->Line($aPos,$this->ticks_pos[$i],$xr,$this->ticks_pos[$i]);
    4581                     }
    4582                     if( $this->mincolor != '' ) {
    4583                         $aImg->PopColor();
    4584                     }
    4585                 }
    4586             }
    4587         }
    4588 
    4589         // Stroke major ticks
    4590         $yu = $aPos - $this->direction*$this->GetMajTickAbsSize();
    4591         $xr = $aPos + $this->direction*$this->GetMajTickAbsSize();
    4592         $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1;
    4593         $n = count($this->maj_ticks_pos);
    4594         for($i=0; $i < $n ; ++$i ) {
    4595             if(!($this->xtick_offset > 0 && $i==$nbrmajticks-1) && !$this->supress_tickmarks) {
    4596                 if( $this->majcolor != '') {
    4597                     $aImg->PushColor($this->majcolor);
    4598                 }
    4599                 if( $hor ) {
    4600                     //if( $this->maj_ticks_pos[$i] <= $limit )
    4601                     $aImg->Line($this->maj_ticks_pos[$i],$aPos,$this->maj_ticks_pos[$i],$yu);
    4602                 }
    4603                 else {
    4604                     //if( $this->maj_ticks_pos[$i] >= $limit )
    4605                     $aImg->Line($aPos,$this->maj_ticks_pos[$i],$xr,$this->maj_ticks_pos[$i]);
    4606                 }
    4607                 if( $this->majcolor != '') {
    4608                     $aImg->PopColor();
    4609                 }
    4610             }
    4611         }
    4612 
     4192        $hor = $aScale->type == 'x';
     4193        $aImg->SetLineWeight($this->weight);
     4194
     4195        // We need to make this an int since comparing it below
     4196        // with the result from round() can give wrong result, such that
     4197        // (40 < 40) == TRUE !!!       
     4198        $limit = (int)$aScale->scale_abs[1];
     4199               
     4200        // A text scale doesn't have any minor ticks
     4201        if( !$aScale->textscale ) {
     4202            // Stroke minor ticks
     4203            $yu = $aPos - $this->direction*$this->GetMinTickAbsSize();
     4204            $xr = $aPos + $this->direction*$this->GetMinTickAbsSize();
     4205            $n = count($this->ticks_pos);
     4206            for($i=0; $i < $n; ++$i ) {
     4207                if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
     4208                    if( $this->mincolor!="" ) $aImg->PushColor($this->mincolor);
     4209                    if( $hor ) {
     4210                        //if( $this->ticks_pos[$i] <= $limit )
     4211                        $aImg->Line($this->ticks_pos[$i],$aPos,$this->ticks_pos[$i],$yu);
     4212                    }
     4213                    else {
     4214                        //if( $this->ticks_pos[$i] >= $limit )
     4215                        $aImg->Line($aPos,$this->ticks_pos[$i],$xr,$this->ticks_pos[$i]);
     4216                    }
     4217                    if( $this->mincolor!="" ) $aImg->PopColor();
     4218                }
     4219            }
     4220        }
     4221
     4222        // Stroke major ticks
     4223        $yu = $aPos - $this->direction*$this->GetMajTickAbsSize();
     4224        $xr = $aPos + $this->direction*$this->GetMajTickAbsSize();
     4225        $nbrmajticks=round(($aScale->GetMaxVal()-$aScale->GetMinVal()-$this->text_label_start )/$this->major_step)+1;
     4226        $n = count($this->maj_ticks_pos);
     4227        for($i=0; $i < $n ; ++$i ) {
     4228            if(!($this->xtick_offset > 0 && $i==$nbrmajticks-1) && !$this->supress_tickmarks) {
     4229                if( $this->majcolor!="" ) $aImg->PushColor($this->majcolor);
     4230                if( $hor ) {
     4231                    //if( $this->maj_ticks_pos[$i] <= $limit )
     4232                    $aImg->Line($this->maj_ticks_pos[$i],$aPos,$this->maj_ticks_pos[$i],$yu);
     4233                }
     4234                else {
     4235                    //if( $this->maj_ticks_pos[$i] >= $limit )
     4236                    $aImg->Line($aPos,$this->maj_ticks_pos[$i],$xr,$this->maj_ticks_pos[$i]);
     4237                }
     4238                if( $this->majcolor!="" ) $aImg->PopColor();
     4239            }
     4240        }
     4241       
    46134242    }
    46144243
    46154244    // Draw linear ticks
    46164245    function Stroke($aImg,$aScale,$aPos) {
    4617         if( $this->iManualTickPos != NULL ) {
    4618             $this->_doManualTickPos($aScale);
    4619         }
    4620         else {
    4621             $this->_doAutoTickPos($aScale);
    4622         }
    4623         $this->_StrokeTicks($aImg,$aScale,$aPos, $aScale->type == 'x' );
    4624     }
    4625 
    4626     //---------------
    4627     // PRIVATE METHODS
     4246        if( $this->iManualTickPos != NULL )
     4247            $this->_doManualTickPos($aScale);
     4248        else
     4249            $this->_doAutoTickPos($aScale);
     4250        $this->_StrokeTicks($aImg,$aScale,$aPos, $aScale->type == 'x' );
     4251    }
     4252
     4253//---------------
     4254// PRIVATE METHODS
    46284255    // Spoecify the offset of the displayed tick mark with the tick "space"
    4629     // Legal values for $o is [0,1] used to adjust where the tick marks and label
     4256    // Legal values for $o is [0,1] used to adjust where the tick marks and label 
    46304257    // should be positioned within the major tick-size
    46314258    // $lo specifies the label offset and $to specifies the tick offset
     
    46334260    // tick but have the labels displayed halfway under the bars.
    46344261    function SetXLabelOffset($aLabelOff,$aTickOff=-1) {
    4635         $this->xlabel_offset=$aLabelOff;
    4636         if( $aTickOff==-1 ) {
    4637             // Same as label offset
    4638             $this->xtick_offset=$aLabelOff;
    4639         }
    4640         else {
    4641             $this->xtick_offset=$aTickOff;
    4642         }
    4643         if( $aLabelOff>0 ) {
    4644             $this->SupressLast(); // The last tick wont fit
    4645         }
     4262        $this->xlabel_offset=$aLabelOff;
     4263        if( $aTickOff==-1 )     // Same as label offset
     4264            $this->xtick_offset=$aLabelOff;
     4265        else
     4266            $this->xtick_offset=$aTickOff;
     4267        if( $aLabelOff>0 )
     4268            $this->SupressLast();       // The last tick wont fit
    46464269    }
    46474270
    46484271    // Which tick label should we start with?
    46494272    function SetTextLabelStart($aTextLabelOff) {
    4650         $this->text_label_start=$aTextLabelOff;
    4651     }
    4652 
     4273        $this->text_label_start=$aTextLabelOff;
     4274    }
     4275       
    46534276} // Class
    46544277
    46554278//===================================================
    46564279// CLASS LinearScale
    4657 // Description: Handle linear scaling between screen and world
     4280// Description: Handle linear scaling between screen and world 
    46584281//===================================================
    46594282class LinearScale {
     
    46744297    public $auto_ticks=false; // When using manual scale should the ticks be automatically set?
    46754298    public $world_abs_size; // Plot area size in pixels (Needed public in jpgraph_radar.php)
     4299    public $world_size; // Plot area size in world coordinates
    46764300    public $intscale=false; // Restrict autoscale to integers
    46774301    protected $autoscale_min=false; // Forced minimum value, auto determine max
    46784302    protected $autoscale_max=false; // Forced maximum value, auto determine min
    46794303    private $gracetop=0,$gracebottom=0;
    4680 
    4681     private $_world_size; // Plot area size in world coordinates
    4682 
    4683     function __construct($aMin=0,$aMax=0,$aType='y') {
    4684         assert($aType=='x' || $aType=='y' );
    4685         assert($aMin<=$aMax);
    4686 
    4687         $this->type=$aType;
    4688         $this->scale=array($aMin,$aMax);
    4689         $this->world_size=$aMax-$aMin;
    4690         $this->ticks = new LinearTicks();
    4691     }
    4692 
     4304//---------------
     4305// CONSTRUCTOR
     4306    function LinearScale($aMin=0,$aMax=0,$aType="y") {
     4307        assert($aType=="x" || $aType=="y" );
     4308        assert($aMin<=$aMax);
     4309               
     4310        $this->type=$aType;
     4311        $this->scale=array($aMin,$aMax);               
     4312        $this->world_size=$aMax-$aMin; 
     4313        $this->ticks = new LinearTicks();
     4314    }
     4315
     4316//---------------
     4317// PUBLIC METHODS       
    46934318    // Check if scale is set or if we should autoscale
    46944319    // We should do this is either scale or ticks has not been set
    46954320    function IsSpecified() {
    4696         if( $this->GetMinVal()==$this->GetMaxVal() ) {  // Scale not set
    4697             return false;
    4698         }
    4699         return true;
    4700     }
    4701 
    4702     // Set the minimum data value when the autoscaling is used.
     4321        if( $this->GetMinVal()==$this->GetMaxVal() ) {          // Scale not set
     4322            return false;
     4323        }
     4324        return true;
     4325    }
     4326       
     4327    // Set the minimum data value when the autoscaling is used. 
    47034328    // Usefull if you want a fix minimum (like 0) but have an
    47044329    // automatic maximum
    47054330    function SetAutoMin($aMin) {
    4706         $this->autoscale_min=$aMin;
    4707     }
    4708 
    4709     // Set the minimum data value when the autoscaling is used.
     4331        $this->autoscale_min=$aMin;
     4332    }
     4333
     4334    // Set the minimum data value when the autoscaling is used. 
    47104335    // Usefull if you want a fix minimum (like 0) but have an
    47114336    // automatic maximum
    47124337    function SetAutoMax($aMax) {
    4713         $this->autoscale_max=$aMax;
     4338        $this->autoscale_max=$aMax;
    47144339    }
    47154340
     
    47174342    // still be set automatically?
    47184343    function SetAutoTicks($aFlag=true) {
    4719         $this->auto_ticks = $aFlag;
     4344        $this->auto_ticks = $aFlag;
    47204345    }
    47214346
    47224347    // Specify scale "grace" value (top and bottom)
    47234348    function SetGrace($aGraceTop,$aGraceBottom=0) {
    4724         if( $aGraceTop<0 || $aGraceBottom < 0  ) {
    4725             JpGraphError::RaiseL(25069);//(" Grace must be larger then 0");
    4726         }
    4727         $this->gracetop=$aGraceTop;
    4728         $this->gracebottom=$aGraceBottom;
    4729     }
    4730 
     4349        if( $aGraceTop<0 || $aGraceBottom < 0  )
     4350            JpGraphError::RaiseL(25069);//(" Grace must be larger then 0");
     4351        $this->gracetop=$aGraceTop;
     4352        $this->gracebottom=$aGraceBottom;
     4353    }
     4354       
    47314355    // Get the minimum value in the scale
    47324356    function GetMinVal() {
    4733         return $this->scale[0];
    4734     }
    4735 
     4357        return $this->scale[0];
     4358    }
     4359       
    47364360    // get maximum value for scale
    47374361    function GetMaxVal() {
    4738         return $this->scale[1];
    4739     }
    4740 
    4741     // Specify a new min/max value for sclae
     4362        return $this->scale[1];
     4363    }
     4364               
     4365    // Specify a new min/max value for sclae   
    47424366    function Update($aImg,$aMin,$aMax) {
    4743         $this->scale=array($aMin,$aMax);
    4744         $this->world_size=$aMax-$aMin;
    4745         $this->InitConstants($aImg);
    4746     }
    4747 
     4367        $this->scale=array($aMin,$aMax);               
     4368        $this->world_size=$aMax-$aMin;         
     4369        $this->InitConstants($aImg);                                   
     4370    }
     4371       
    47484372    // Translate between world and screen
    47494373    function Translate($aCoord) {
    4750         if( !is_numeric($aCoord) ) {
    4751             if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' ) {
    4752                 JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.');
    4753             }
    4754             return 0;
    4755         }
    4756         else {
    4757             return round($this->off+($aCoord - $this->scale[0]) * $this->scale_factor);
    4758         }
    4759     }
    4760 
     4374        if( !is_numeric($aCoord) ) {
     4375            if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x' )
     4376                JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.');
     4377            return 0;
     4378        }
     4379        else {
     4380            return $this->off+($aCoord - $this->scale[0]) * $this->scale_factor;
     4381        }
     4382    }
     4383       
    47614384    // Relative translate (don't include offset) usefull when we just want
    47624385    // to know the relative position (in pixels) on the axis
    47634386    function RelTranslate($aCoord) {
    4764         if( !is_numeric($aCoord) ) {
    4765             if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x'  ) {
    4766                 JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.');
    4767             }
    4768             return 0;
    4769         }
    4770         else {
    4771             return ($aCoord - $this->scale[0]) * $this->scale_factor;
    4772         }
    4773     }
    4774 
     4387        if( !is_numeric($aCoord) ) {
     4388            if( $aCoord != '' && $aCoord != '-' && $aCoord != 'x'  )
     4389                JpGraphError::RaiseL(25070);//('Your data contains non-numeric values.');
     4390            return 0;
     4391        }
     4392        else {
     4393            return ($aCoord - $this->scale[0]) * $this->scale_factor;
     4394        }
     4395    }
     4396       
    47754397    // Restrict autoscaling to only use integers
    47764398    function SetIntScale($aIntScale=true) {
    4777         $this->intscale=$aIntScale;
    4778     }
    4779 
     4399        $this->intscale=$aIntScale;
     4400    }
     4401       
    47804402    // Calculate an integer autoscale
    47814403    function IntAutoScale($img,$min,$max,$maxsteps,$majend=true) {
    4782         // Make sure limits are integers
    4783         $min=floor($min);
    4784         $max=ceil($max);
    4785         if( abs($min-$max)==0 ) {
    4786             --$min; ++$max;
    4787         }
    4788         $maxsteps = floor($maxsteps);
    4789 
    4790         $gracetop=round(($this->gracetop/100.0)*abs($max-$min));
    4791         $gracebottom=round(($this->gracebottom/100.0)*abs($max-$min));
    4792         if( is_numeric($this->autoscale_min) ) {
    4793             $min = ceil($this->autoscale_min);
    4794             if( $min >= $max ) {
    4795                 JpGraphError::RaiseL(25071);//('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.');
    4796             }
    4797         }
    4798 
    4799         if( is_numeric($this->autoscale_max) ) {
    4800             $max = ceil($this->autoscale_max);
    4801             if( $min >= $max ) {
    4802                 JpGraphError::RaiseL(25072);//('You have specified a max value with SetAutoMax() which is smaller than the miminum value used for the scale. This is not possible.');
    4803             }
    4804         }
    4805 
    4806         if( abs($min-$max ) == 0 ) {
    4807             ++$max;
    4808             --$min;
    4809         }
    4810 
    4811         $min -= $gracebottom;
    4812         $max += $gracetop;
    4813 
    4814         // First get tickmarks as multiples of 1, 10, ...
    4815         if( $majend ) {
    4816             list($num1steps,$adj1min,$adj1max,$maj1step) = $this->IntCalcTicks($maxsteps,$min,$max,1);
    4817         }
    4818         else {
    4819             $adj1min = $min;
    4820             $adj1max = $max;
    4821             list($num1steps,$maj1step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,1);
    4822         }
    4823 
    4824         if( abs($min-$max) > 2 ) {
    4825             // Then get tick marks as 2:s 2, 20, ...
    4826             if( $majend ) {
    4827                 list($num2steps,$adj2min,$adj2max,$maj2step) = $this->IntCalcTicks($maxsteps,$min,$max,5);
    4828             }
    4829             else {
    4830                 $adj2min = $min;
    4831                 $adj2max = $max;
    4832                 list($num2steps,$maj2step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,5);
    4833             }
    4834         }
    4835         else {
    4836             $num2steps = 10000; // Dummy high value so we don't choose this
    4837         }
    4838 
    4839         if( abs($min-$max) > 5 ) {
    4840             // Then get tickmarks as 5:s 5, 50, 500, ...
    4841             if( $majend ) {
    4842                 list($num5steps,$adj5min,$adj5max,$maj5step) = $this->IntCalcTicks($maxsteps,$min,$max,2);
    4843             }
    4844             else {
    4845                 $adj5min = $min;
    4846                 $adj5max = $max;
    4847                 list($num5steps,$maj5step) = $this->IntCalcTicksFreeze($maxsteps,$min,$max,2);
    4848             }
    4849         }
    4850         else {
    4851             $num5steps = 10000; // Dummy high value so we don't choose this
    4852         }
    4853 
    4854         // Check to see whichof 1:s, 2:s or 5:s fit better with
    4855         // the requested number of major ticks
    4856         $match1=abs($num1steps-$maxsteps);
    4857         $match2=abs($num2steps-$maxsteps);
    4858         if( !empty($maj5step) && $maj5step > 1 ) {
    4859             $match5=abs($num5steps-$maxsteps);
    4860         }
    4861         else {
    4862             $match5=10000;  // Dummy high value
    4863         }
    4864 
    4865         // Compare these three values and see which is the closest match
    4866         // We use a 0.6 weight to gravitate towards multiple of 5:s
    4867         if( $match1 < $match2 ) {
    4868             if( $match1 < $match5 ) $r=1;
    4869             else  $r=3;
    4870         }
    4871         else {
    4872             if( $match2 < $match5 ) $r=2;
    4873             else $r=3;
    4874         }
    4875         // Minsteps are always the same as maxsteps for integer scale
    4876         switch( $r ) {
    4877             case 1:
    4878                 $this->ticks->Set($maj1step,$maj1step);
    4879                 $this->Update($img,$adj1min,$adj1max);
    4880                 break;
    4881             case 2:
    4882                 $this->ticks->Set($maj2step,$maj2step);
    4883                 $this->Update($img,$adj2min,$adj2max);
    4884                 break;
    4885             case 3:
    4886                 $this->ticks->Set($maj5step,$maj5step);
    4887                 $this->Update($img,$adj5min,$adj5max);
    4888                 break;
    4889             default:
    4890                 JpGraphError::RaiseL(25073,$r);//('Internal error. Integer scale algorithm comparison out of bound (r=$r)');
    4891         }
    4892     }
    4893 
    4894 
     4404        // Make sure limits are integers
     4405        $min=floor($min);
     4406        $max=ceil($max);
     4407        if( abs($min-$max)==0 ) {
     4408            --$min; ++$max;
     4409        }
     4410        $maxsteps = floor($maxsteps);
     4411               
     4412        $gracetop=round(($this->gracetop/100.0)*abs($max-$min));
     4413        $gracebottom=round(($this->gracebottom/100.0)*abs($max-$min));
     4414        if( is_numeric($this->autoscale_min) ) {
     4415            $min = ceil($this->autoscale_min);
     4416            if( $min >= $max ) {
     4417                JpGraphError::RaiseL(25071);//('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.');
     4418            }
     4419        }
     4420
     4421        if( is_numeric($this->autoscale_max) ) {
     4422            $max = ceil($this->autoscale_max);
     4423            if( $min >= $max ) {
     4424                JpGraphError::RaiseL(25072);//('You have specified a max value with SetAutoMax() which is smaller than the miminum value used for the scale. This is not possible.');
     4425            }
     4426        }
     4427
     4428        if( abs($min-$max ) == 0 ) {
     4429            ++$max;
     4430            --$min;
     4431        }
     4432                       
     4433        $min -= $gracebottom;
     4434        $max += $gracetop;             
     4435
     4436        // First get tickmarks as multiples of 1, 10, ...       
     4437        if( $majend ) {
     4438            list($num1steps,$adj1min,$adj1max,$maj1step) =
     4439                $this->IntCalcTicks($maxsteps,$min,$max,1);
     4440        }
     4441        else {
     4442            $adj1min = $min;
     4443            $adj1max = $max;
     4444            list($num1steps,$maj1step) =
     4445                $this->IntCalcTicksFreeze($maxsteps,$min,$max,1);
     4446        }
     4447
     4448        if( abs($min-$max) > 2 ) {
     4449            // Then get tick marks as 2:s 2, 20, ...
     4450            if( $majend ) {
     4451                list($num2steps,$adj2min,$adj2max,$maj2step) =
     4452                    $this->IntCalcTicks($maxsteps,$min,$max,5);
     4453            }
     4454            else {
     4455                $adj2min = $min;
     4456                $adj2max = $max;
     4457                list($num2steps,$maj2step) =
     4458                    $this->IntCalcTicksFreeze($maxsteps,$min,$max,5);
     4459            }
     4460        }
     4461        else {
     4462            $num2steps = 10000; // Dummy high value so we don't choose this
     4463        }
     4464       
     4465        if( abs($min-$max) > 5 ) {     
     4466            // Then get tickmarks as 5:s 5, 50, 500, ...
     4467            if( $majend ) {
     4468                list($num5steps,$adj5min,$adj5max,$maj5step) =
     4469                    $this->IntCalcTicks($maxsteps,$min,$max,2);
     4470            }
     4471            else {
     4472                $adj5min = $min;
     4473                $adj5max = $max;
     4474                list($num5steps,$maj5step) =
     4475                    $this->IntCalcTicksFreeze($maxsteps,$min,$max,2);
     4476            }
     4477        }
     4478        else {
     4479            $num5steps = 10000; // Dummy high value so we don't choose this             
     4480        }
     4481       
     4482        // Check to see whichof 1:s, 2:s or 5:s fit better with
     4483        // the requested number of major ticks         
     4484        $match1=abs($num1steps-$maxsteps);             
     4485        $match2=abs($num2steps-$maxsteps);
     4486        if( !empty($maj5step) && $maj5step > 1 )
     4487            $match5=abs($num5steps-$maxsteps);
     4488        else
     4489            $match5=10000;      // Dummy high value
     4490               
     4491        // Compare these three values and see which is the closest match
     4492        // We use a 0.6 weight to gravitate towards multiple of 5:s
     4493        if( $match1 < $match2 ) {
     4494            if( $match1 < $match5 )
     4495                $r=1;                   
     4496            else
     4497                $r=3;
     4498        }
     4499        else {
     4500            if( $match2 < $match5 )
     4501                $r=2;                   
     4502            else
     4503                $r=3;           
     4504        }       
     4505        // Minsteps are always the same as maxsteps for integer scale
     4506        switch( $r ) {
     4507            case 1:
     4508                $this->ticks->Set($maj1step,$maj1step);
     4509                $this->Update($img,$adj1min,$adj1max);
     4510                break;                 
     4511            case 2:
     4512                $this->ticks->Set($maj2step,$maj2step);
     4513                $this->Update($img,$adj2min,$adj2max);         
     4514                break;                                                                 
     4515            case 3:
     4516                $this->ticks->Set($maj5step,$maj5step);         
     4517                $this->Update($img,$adj5min,$adj5max);
     4518                break;                 
     4519            default:
     4520                JpGraphError::RaiseL(25073,$r);//('Internal error. Integer scale algorithm comparison out of bound (r=$r)');
     4521        }               
     4522    }
     4523       
     4524       
    48954525    // Calculate autoscale. Used if user hasn't given a scale and ticks
    48964526    // $maxsteps is the maximum number of major tickmarks allowed.
    48974527    function AutoScale($img,$min,$max,$maxsteps,$majend=true) {
    4898 
    4899         if( !is_numeric($min) || !is_numeric($max) ) {
    4900             JpGraphError::Raise(25044);
    4901         }
    4902 
    4903         if( $this->intscale ) {
    4904             $this->IntAutoScale($img,$min,$max,$maxsteps,$majend);
    4905             return;
    4906         }
    4907         if( abs($min-$max) < 0.00001 ) {
    4908             // We need some difference to be able to autoscale
    4909             // make it 5% above and 5% below value
    4910             if( $min==0 && $max==0 ) {  // Special case
    4911                 $min=-1; $max=1;
    4912             }
    4913             else {
    4914                 $delta = (abs($max)+abs($min))*0.005;
    4915                 $min -= $delta;
    4916                 $max += $delta;
    4917             }
    4918         }
    4919 
    4920         $gracetop=($this->gracetop/100.0)*abs($max-$min);
    4921         $gracebottom=($this->gracebottom/100.0)*abs($max-$min);
    4922         if( is_numeric($this->autoscale_min) ) {
    4923             $min = $this->autoscale_min;
    4924             if( $min >= $max ) {
    4925                 JpGraphError::RaiseL(25071);//('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.');
    4926             }
    4927             if( abs($min-$max ) < 0.001 ) {
    4928                 $max *= 1.2;
    4929             }
    4930         }
    4931 
    4932         if( is_numeric($this->autoscale_max) ) {
    4933             $max = $this->autoscale_max;
    4934             if( $min >= $max ) {
    4935                 JpGraphError::RaiseL(25072);//('You have specified a max value with SetAutoMax() which is smaller than the miminum value used for the scale. This is not possible.');
    4936             }
    4937             if( abs($min-$max ) < 0.001 ) {
    4938                 $min *= 0.8;
    4939             }
    4940         }
    4941 
    4942         $min -= $gracebottom;
    4943         $max += $gracetop;
    4944 
    4945         // First get tickmarks as multiples of 0.1, 1, 10, ...
    4946         if( $majend ) {
    4947             list($num1steps,$adj1min,$adj1max,$min1step,$maj1step) = $this->CalcTicks($maxsteps,$min,$max,1,2);
    4948         }
    4949         else {
    4950             $adj1min=$min;
    4951             $adj1max=$max;
    4952             list($num1steps,$min1step,$maj1step) = $this->CalcTicksFreeze($maxsteps,$min,$max,1,2,false);
    4953         }
    4954 
    4955         // Then get tick marks as 2:s 0.2, 2, 20, ...
    4956         if( $majend ) {
    4957             list($num2steps,$adj2min,$adj2max,$min2step,$maj2step) = $this->CalcTicks($maxsteps,$min,$max,5,2);
    4958         }
    4959         else {
    4960             $adj2min=$min;
    4961             $adj2max=$max;
    4962             list($num2steps,$min2step,$maj2step) = $this->CalcTicksFreeze($maxsteps,$min,$max,5,2,false);
    4963         }
    4964 
    4965         // Then get tickmarks as 5:s 0.05, 0.5, 5, 50, ...
    4966         if( $majend ) {
    4967             list($num5steps,$adj5min,$adj5max,$min5step,$maj5step) = $this->CalcTicks($maxsteps,$min,$max,2,5);
    4968         }
    4969         else {
    4970             $adj5min=$min;
    4971             $adj5max=$max;
    4972             list($num5steps,$min5step,$maj5step) = $this->CalcTicksFreeze($maxsteps,$min,$max,2,5,false);
    4973         }
    4974 
    4975         // Check to see whichof 1:s, 2:s or 5:s fit better with
    4976         // the requested number of major ticks
    4977         $match1=abs($num1steps-$maxsteps);
    4978         $match2=abs($num2steps-$maxsteps);
    4979         $match5=abs($num5steps-$maxsteps);
    4980 
    4981         // Compare these three values and see which is the closest match
    4982         // We use a 0.8 weight to gravitate towards multiple of 5:s
    4983         $r=$this->MatchMin3($match1,$match2,$match5,0.8);
    4984         switch( $r ) {
    4985             case 1:
    4986                 $this->Update($img,$adj1min,$adj1max);
    4987                 $this->ticks->Set($maj1step,$min1step);
    4988                 break;
    4989             case 2:
    4990                 $this->Update($img,$adj2min,$adj2max);
    4991                 $this->ticks->Set($maj2step,$min2step);
    4992                 break;
    4993             case 3:
    4994                 $this->Update($img,$adj5min,$adj5max);
    4995                 $this->ticks->Set($maj5step,$min5step);
    4996                 break;
    4997         }
    4998     }
    4999 
    5000     //---------------
    5001     // PRIVATE METHODS
     4528        if( $this->intscale ) {
     4529            $this->IntAutoScale($img,$min,$max,$maxsteps,$majend);
     4530            return;
     4531        }
     4532        if( abs($min-$max) < 0.00001 ) {
     4533            // We need some difference to be able to autoscale
     4534            // make it 5% above and 5% below value
     4535            if( $min==0 && $max==0 ) {          // Special case
     4536                $min=-1; $max=1;
     4537            }
     4538            else {
     4539                $delta = (abs($max)+abs($min))*0.005;
     4540                $min -= $delta;
     4541                $max += $delta;
     4542            }
     4543        }
     4544               
     4545        $gracetop=($this->gracetop/100.0)*abs($max-$min);
     4546        $gracebottom=($this->gracebottom/100.0)*abs($max-$min);
     4547        if( is_numeric($this->autoscale_min) ) {
     4548            $min = $this->autoscale_min;
     4549            if( $min >= $max ) {
     4550                JpGraphError::RaiseL(25071);//('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.');
     4551            }
     4552            if( abs($min-$max ) < 0.00001 )
     4553                $max *= 1.2;
     4554        }
     4555
     4556        if( is_numeric($this->autoscale_max) ) {
     4557            $max = $this->autoscale_max;
     4558            if( $min >= $max ) {
     4559                JpGraphError::RaiseL(25072);//('You have specified a max value with SetAutoMax() which is smaller than the miminum value used for the scale. This is not possible.');
     4560            }
     4561            if( abs($min-$max ) < 0.00001 )
     4562                $min *= 0.8;
     4563        }
     4564
     4565        $min -= $gracebottom;
     4566        $max += $gracetop;
     4567
     4568
     4569        // First get tickmarks as multiples of 0.1, 1, 10, ... 
     4570        if( $majend ) {
     4571            list($num1steps,$adj1min,$adj1max,$min1step,$maj1step) =
     4572                $this->CalcTicks($maxsteps,$min,$max,1,2);
     4573        }
     4574        else {
     4575            $adj1min=$min;
     4576            $adj1max=$max;
     4577            list($num1steps,$min1step,$maj1step) =
     4578                $this->CalcTicksFreeze($maxsteps,$min,$max,1,2,false);
     4579        }
     4580               
     4581        // Then get tick marks as 2:s 0.2, 2, 20, ...
     4582        if( $majend ) {
     4583            list($num2steps,$adj2min,$adj2max,$min2step,$maj2step) =
     4584                $this->CalcTicks($maxsteps,$min,$max,5,2);
     4585        }
     4586        else {
     4587            $adj2min=$min;
     4588            $adj2max=$max;
     4589            list($num2steps,$min2step,$maj2step) =
     4590                $this->CalcTicksFreeze($maxsteps,$min,$max,5,2,false);
     4591        }
     4592               
     4593        // Then get tickmarks as 5:s 0.05, 0.5, 5, 50, ...
     4594        if( $majend ) {
     4595            list($num5steps,$adj5min,$adj5max,$min5step,$maj5step) =
     4596                $this->CalcTicks($maxsteps,$min,$max,2,5);             
     4597        }
     4598        else {
     4599            $adj5min=$min;
     4600            $adj5max=$max;
     4601            list($num5steps,$min5step,$maj5step) =
     4602                $this->CalcTicksFreeze($maxsteps,$min,$max,2,5,false);
     4603        }
     4604
     4605        // Check to see whichof 1:s, 2:s or 5:s fit better with
     4606        // the requested number of major ticks         
     4607        $match1=abs($num1steps-$maxsteps);             
     4608        $match2=abs($num2steps-$maxsteps);
     4609        $match5=abs($num5steps-$maxsteps);
     4610        // Compare these three values and see which is the closest match
     4611        // We use a 0.8 weight to gravitate towards multiple of 5:s
     4612        $r=$this->MatchMin3($match1,$match2,$match5,0.8);
     4613        switch( $r ) {
     4614            case 1:
     4615                $this->Update($img,$adj1min,$adj1max);
     4616                $this->ticks->Set($maj1step,$min1step);
     4617                break;                 
     4618            case 2:
     4619                $this->Update($img,$adj2min,$adj2max);         
     4620                $this->ticks->Set($maj2step,$min2step);
     4621                break;                                                                 
     4622            case 3:
     4623                $this->Update($img,$adj5min,$adj5max);
     4624                $this->ticks->Set($maj5step,$min5step);         
     4625                break;                 
     4626        }
     4627    }
     4628
     4629//---------------
     4630// PRIVATE METHODS     
    50024631
    50034632    // This method recalculates all constants that are depending on the
     
    50064635    // that image. Should really be installed as an observer of that image.
    50074636    function InitConstants($img) {
    5008         if( $this->type=='x' ) {
    5009             $this->world_abs_size=$img->width - $img->left_margin - $img->right_margin;
    5010             $this->off=$img->left_margin;
    5011             $this->scale_factor = 0;
    5012             if( $this->world_size > 0 ) {
    5013                 $this->scale_factor=$this->world_abs_size/($this->world_size*0.999999);
    5014             }
    5015         }
    5016         else { // y scale
    5017             $this->world_abs_size=$img->height - $img->top_margin - $img->bottom_margin;
    5018             $this->off=$img->top_margin+$this->world_abs_size;
    5019             $this->scale_factor = 0;
    5020             if( $this->world_size > 0 ) {
    5021                 $this->scale_factor=-$this->world_abs_size/($this->world_size*0.999999);
    5022             }
    5023         }
    5024         $size = $this->world_size * $this->scale_factor;
    5025         $this->scale_abs=array($this->off,$this->off + $size);
    5026     }
    5027 
     4637        if( $this->type=="x" ) {
     4638            $this->world_abs_size=$img->width - $img->left_margin - $img->right_margin;
     4639            $this->off=$img->left_margin;
     4640            $this->scale_factor = 0;
     4641            if( $this->world_size > 0 )
     4642                $this->scale_factor=$this->world_abs_size/($this->world_size*1.0);
     4643        }
     4644        else { // y scale
     4645            $this->world_abs_size=$img->height - $img->top_margin - $img->bottom_margin;
     4646            $this->off=$img->top_margin+$this->world_abs_size;                 
     4647            $this->scale_factor = 0;                   
     4648            if( $this->world_size > 0 )                 
     4649                $this->scale_factor=-$this->world_abs_size/($this->world_size*1.0);     
     4650        }
     4651        $size = $this->world_size * $this->scale_factor;
     4652        $this->scale_abs=array($this->off,$this->off + $size); 
     4653    }
     4654       
    50284655    // Initialize the conversion constants for this scale
    50294656    // This tries to pre-calculate as much as possible to speed up the
    50304657    // actual conversion (with Translate()) later on
    5031     // $start =scale start in absolute pixels (for x-scale this is an y-position
    5032     //    and for an y-scale this is an x-position
    5033     // $len   =absolute length in pixels of scale
     4658    // $start   =scale start in absolute pixels (for x-scale this is an y-position
     4659    //                          and for an y-scale this is an x-position
     4660    // $len             =absolute length in pixels of scale                     
    50344661    function SetConstants($aStart,$aLen) {
    5035         $this->world_abs_size=$aLen;
    5036         $this->off=$aStart;
    5037 
    5038         if( $this->world_size<=0 ) {
    5039             // This should never ever happen !!
    5040             JpGraphError::RaiseL(25074);
    5041             //("You have unfortunately stumbled upon a bug in JpGraph. It seems like the scale range is ".$this->world_size." [for ".$this->type." scale] <br> Please report Bug #01 to info@jpgraph.net and include the script that gave this error. This problem could potentially be caused by trying to use \"illegal\" values in the input data arrays (like trying to send in strings or only NULL values) which causes the autoscaling to fail.");
    5042         }
    5043 
    5044         // scale_factor = number of pixels per world unit
    5045         $this->scale_factor=$this->world_abs_size/($this->world_size*1.0);
    5046 
    5047         // scale_abs = start and end points of scale in absolute pixels
    5048         $this->scale_abs=array($this->off,$this->off+$this->world_size*$this->scale_factor);
    5049     }
    5050 
    5051 
     4662        $this->world_abs_size=$aLen;
     4663        $this->off=$aStart;
     4664               
     4665        if( $this->world_size<=0 ) {
     4666            // This should never ever happen !!
     4667            JpGraphError::RaiseL(25074);
     4668//("You have unfortunately stumbled upon a bug in JpGraph. It seems like the scale range is ".$this->world_size." [for ".$this->type." scale] <br> Please report Bug #01 to jpgraph@aditus.nu and include the script that gave this error. This problem could potentially be caused by trying to use \"illegal\" values in the input data arrays (like trying to send in strings or only NULL values) which causes the autoscaling to fail.");
     4669
     4670        }
     4671               
     4672        // scale_factor = number of pixels per world unit
     4673        $this->scale_factor=$this->world_abs_size/($this->world_size*1.0);
     4674               
     4675        // scale_abs = start and end points of scale in absolute pixels
     4676        $this->scale_abs=array($this->off,$this->off+$this->world_size*$this->scale_factor);           
     4677    }
     4678       
     4679       
    50524680    // Calculate number of ticks steps with a specific division
    50534681    // $a is the divisor of 10**x to generate the first maj tick intervall
     
    50564684    // $a=2, $b=5 give major ticks with multiple of 5:s ...,0.5,5,50,...
    50574685    // We return a vector of
    5058     //  [$numsteps,$adjmin,$adjmax,$minstep,$majstep]
     4686    //  [$numsteps,$adjmin,$adjmax,$minstep,$majstep]
    50594687    // If $majend==true then the first and last marks on the axis will be major
    50604688    // labeled tick marks otherwise it will be adjusted to the closest min tick mark
    50614689    function CalcTicks($maxsteps,$min,$max,$a,$b,$majend=true) {
    5062         $diff=$max-$min;
    5063         if( $diff==0 ) {
    5064             $ld=0;
    5065         }
    5066         else {
    5067             $ld=floor(log10($diff));
    5068         }
    5069 
    5070         // Gravitate min towards zero if we are close
    5071         if( $min>0 && $min < pow(10,$ld) ) $min=0;
    5072 
    5073         //$majstep=pow(10,$ld-1)/$a;
    5074         $majstep=pow(10,$ld)/$a;
    5075         $minstep=$majstep/$b;
    5076 
    5077         $adjmax=ceil($max/$minstep)*$minstep;
    5078         $adjmin=floor($min/$minstep)*$minstep;
    5079         $adjdiff = $adjmax-$adjmin;
    5080         $numsteps=$adjdiff/$majstep;
    5081 
    5082         while( $numsteps>$maxsteps ) {
    5083             $majstep=pow(10,$ld)/$a;
    5084             $numsteps=$adjdiff/$majstep;
    5085             ++$ld;
    5086         }
    5087 
    5088         $minstep=$majstep/$b;
    5089         $adjmin=floor($min/$minstep)*$minstep;
    5090         $adjdiff = $adjmax-$adjmin;
    5091         if( $majend ) {
    5092             $adjmin = floor($min/$majstep)*$majstep;
    5093             $adjdiff = $adjmax-$adjmin;
    5094             $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin;
    5095         }
    5096         else {
    5097             $adjmax=ceil($max/$minstep)*$minstep;
    5098         }
    5099 
    5100         return array($numsteps,$adjmin,$adjmax,$minstep,$majstep);
     4690        $diff=$max-$min;
     4691        if( $diff==0 )
     4692            $ld=0;
     4693        else
     4694            $ld=floor(log10($diff));
     4695
     4696        // Gravitate min towards zero if we are close           
     4697        if( $min>0 && $min < pow(10,$ld) ) $min=0;
     4698               
     4699        //$majstep=pow(10,$ld-1)/$a;
     4700        $majstep=pow(10,$ld)/$a;
     4701        $minstep=$majstep/$b;
     4702       
     4703        $adjmax=ceil($max/$minstep)*$minstep;
     4704        $adjmin=floor($min/$minstep)*$minstep; 
     4705        $adjdiff = $adjmax-$adjmin;
     4706        $numsteps=$adjdiff/$majstep;
     4707       
     4708        while( $numsteps>$maxsteps ) {
     4709            $majstep=pow(10,$ld)/$a;
     4710            $numsteps=$adjdiff/$majstep;
     4711            ++$ld;
     4712        }
     4713
     4714        $minstep=$majstep/$b;
     4715        $adjmin=floor($min/$minstep)*$minstep; 
     4716        $adjdiff = $adjmax-$adjmin;             
     4717        if( $majend ) {
     4718            $adjmin = floor($min/$majstep)*$majstep;   
     4719            $adjdiff = $adjmax-$adjmin;         
     4720            $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin;
     4721        }
     4722        else
     4723            $adjmax=ceil($max/$minstep)*$minstep;
     4724
     4725        return array($numsteps,$adjmin,$adjmax,$minstep,$majstep);
    51014726    }
    51024727
    51034728    function CalcTicksFreeze($maxsteps,$min,$max,$a,$b) {
    5104         // Same as CalcTicks but don't adjust min/max values
    5105         $diff=$max-$min;
    5106         if( $diff==0 ) {
    5107             $ld=0;
    5108         }
    5109         else {
    5110             $ld=floor(log10($diff));
    5111         }
    5112 
    5113         //$majstep=pow(10,$ld-1)/$a;
    5114         $majstep=pow(10,$ld)/$a;
    5115         $minstep=$majstep/$b;
    5116         $numsteps=floor($diff/$majstep);
    5117 
    5118         while( $numsteps > $maxsteps ) {
    5119             $majstep=pow(10,$ld)/$a;
    5120             $numsteps=floor($diff/$majstep);
    5121             ++$ld;
    5122         }
    5123         $minstep=$majstep/$b;
    5124         return array($numsteps,$minstep,$majstep);
    5125     }
    5126 
    5127 
     4729        // Same as CalcTicks but don't adjust min/max values
     4730        $diff=$max-$min;
     4731        if( $diff==0 )
     4732            $ld=0;
     4733        else
     4734            $ld=floor(log10($diff));
     4735
     4736        //$majstep=pow(10,$ld-1)/$a;
     4737        $majstep=pow(10,$ld)/$a;
     4738        $minstep=$majstep/$b;
     4739        $numsteps=floor($diff/$majstep);
     4740       
     4741        while( $numsteps > $maxsteps ) {
     4742            $majstep=pow(10,$ld)/$a;
     4743            $numsteps=floor($diff/$majstep);
     4744            ++$ld;
     4745        }
     4746        $minstep=$majstep/$b;
     4747        return array($numsteps,$minstep,$majstep);
     4748    }
     4749
     4750       
    51284751    function IntCalcTicks($maxsteps,$min,$max,$a,$majend=true) {
    5129         $diff=$max-$min;
    5130         if( $diff==0 ) {
    5131             JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.');
    5132         }
    5133         else {
    5134             $ld=floor(log10($diff));
    5135         }
    5136 
    5137         // Gravitate min towards zero if we are close
    5138         if( $min>0 && $min < pow(10,$ld) ) {
    5139             $min=0;
    5140         }
    5141         if( $ld == 0 ) {
    5142             $ld=1;
    5143         }
    5144         if( $a == 1 ) {
    5145             $majstep = 1;
    5146         }
    5147         else {
    5148             $majstep=pow(10,$ld)/$a;
    5149         }
    5150         $adjmax=ceil($max/$majstep)*$majstep;
    5151 
    5152         $adjmin=floor($min/$majstep)*$majstep;
    5153         $adjdiff = $adjmax-$adjmin;
    5154         $numsteps=$adjdiff/$majstep;
    5155         while( $numsteps>$maxsteps ) {
    5156             $majstep=pow(10,$ld)/$a;
    5157             $numsteps=$adjdiff/$majstep;
    5158             ++$ld;
    5159         }
    5160 
    5161         $adjmin=floor($min/$majstep)*$majstep;
    5162         $adjdiff = $adjmax-$adjmin;
    5163         if( $majend ) {
    5164             $adjmin = floor($min/$majstep)*$majstep;
    5165             $adjdiff = $adjmax-$adjmin;
    5166             $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin;
    5167         }
    5168         else {
    5169             $adjmax=ceil($max/$majstep)*$majstep;
    5170         }
    5171 
    5172         return array($numsteps,$adjmin,$adjmax,$majstep);
     4752        $diff=$max-$min;
     4753        if( $diff==0 )
     4754            JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.');
     4755        else
     4756            $ld=floor(log10($diff));
     4757               
     4758        // Gravitate min towards zero if we are close           
     4759        if( $min>0 && $min < pow(10,$ld) ) $min=0;
     4760               
     4761        if( $ld == 0 ) $ld=1;
     4762       
     4763        if( $a == 1 )
     4764            $majstep = 1;
     4765        else
     4766            $majstep=pow(10,$ld)/$a;
     4767        $adjmax=ceil($max/$majstep)*$majstep;
     4768
     4769        $adjmin=floor($min/$majstep)*$majstep; 
     4770        $adjdiff = $adjmax-$adjmin;
     4771        $numsteps=$adjdiff/$majstep;
     4772        while( $numsteps>$maxsteps ) {
     4773            $majstep=pow(10,$ld)/$a;
     4774            $numsteps=$adjdiff/$majstep;
     4775            ++$ld;
     4776        }
     4777               
     4778        $adjmin=floor($min/$majstep)*$majstep; 
     4779        $adjdiff = $adjmax-$adjmin;             
     4780        if( $majend ) {
     4781            $adjmin = floor($min/$majstep)*$majstep;   
     4782            $adjdiff = $adjmax-$adjmin;         
     4783            $adjmax = ceil($adjdiff/$majstep)*$majstep+$adjmin;
     4784        }
     4785        else
     4786            $adjmax=ceil($max/$majstep)*$majstep;
     4787                       
     4788        return array($numsteps,$adjmin,$adjmax,$majstep);               
    51734789    }
    51744790
    51754791
    51764792    function IntCalcTicksFreeze($maxsteps,$min,$max,$a) {
    5177         // Same as IntCalcTick but don't change min/max values
    5178         $diff=$max-$min;
    5179         if( $diff==0 ) {
    5180             JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.');
    5181         }
    5182         else {
    5183             $ld=floor(log10($diff));
    5184         }
    5185         if( $ld == 0 ) {
    5186             $ld=1;
    5187         }
    5188         if( $a == 1 ) {
    5189             $majstep = 1;
    5190         }
    5191         else {
    5192             $majstep=pow(10,$ld)/$a;
    5193         }
    5194 
    5195         $numsteps=floor($diff/$majstep);
    5196         while( $numsteps > $maxsteps ) {
    5197             $majstep=pow(10,$ld)/$a;
    5198             $numsteps=floor($diff/$majstep);
    5199             ++$ld;
    5200         }
    5201 
    5202         return array($numsteps,$majstep);
    5203     }
    5204 
     4793        // Same as IntCalcTick but don't change min/max values
     4794        $diff=$max-$min;
     4795        if( $diff==0 )
     4796            JpGraphError::RaiseL(25075);//('Can\'t automatically determine ticks since min==max.');
     4797        else
     4798            $ld=floor(log10($diff));
     4799               
     4800        if( $ld == 0 ) $ld=1;
     4801       
     4802        if( $a == 1 )
     4803            $majstep = 1;
     4804        else
     4805            $majstep=pow(10,$ld)/$a;
     4806
     4807        $numsteps=floor($diff/$majstep);
     4808        while( $numsteps > $maxsteps ) {
     4809            $majstep=pow(10,$ld)/$a;
     4810            $numsteps=floor($diff/$majstep);
     4811            ++$ld;
     4812        }
     4813                                       
     4814        return array($numsteps,$majstep);               
     4815    }
     4816
     4817
     4818       
    52054819    // Determine the minimum of three values witha  weight for last value
    52064820    function MatchMin3($a,$b,$c,$weight) {
    5207         if( $a < $b ) {
    5208             if( $a < ($c*$weight) ) {
    5209                 return 1; // $a smallest
    5210             }
    5211             else {
    5212                 return 3; // $c smallest
    5213             }
    5214         }
    5215         elseif( $b < ($c*$weight) ) {
    5216             return 2; // $b smallest
    5217         }
    5218         return 3; // $c smallest
    5219     }
    5220 
    5221     function __get($name) {
    5222         $variable_name = '_' . $name;
    5223 
    5224         if (isset($this->$variable_name)) {
    5225             return $this->$variable_name * SUPERSAMPLING_SCALE;
    5226         } else {
    5227             JpGraphError::RaiseL('25132', $name);
    5228         }
    5229     }
    5230 
    5231     function __set($name, $value) {
    5232         $this->{'_'.$name} = $value;
     4821        if( $a < $b ) {
     4822            if( $a < ($c*$weight) )
     4823                return 1; // $a smallest
     4824            else
     4825                return 3; // $c smallest
     4826        }
     4827        elseif( $b < ($c*$weight) )
     4828            return 2; // $b smallest
     4829        return 3; // $c smallest
    52334830    }
    52344831} // Class
     
    52424839    public $margin=5;
    52434840    public $show=false;
    5244     public $valign='',$halign='center';
    5245     public $format='%.1f',$negformat='';
    5246     private $ff=FF_DEFAULT,$fs=FS_NORMAL,$fsize=8;
     4841    public $valign="",$halign="center";
     4842    public $format="%.1f",$negformat="";
     4843    private $ff=FF_FONT1,$fs=FS_NORMAL,$fsize=10;
    52474844    private $iFormCallback='';
    52484845    private $angle=0;
    5249     private $color='navy',$negcolor='';
     4846    private $color="navy",$negcolor="";
    52504847    private $iHideZero=false;
    5251     public $txt=null;
    5252 
    5253     function __construct() {
    5254                 $this->txt = new Text();
    5255     }
    52564848
    52574849    function Show($aFlag=true) {
    5258         $this->show=$aFlag;
    5259     }
    5260 
    5261     function SetColor($aColor,$aNegcolor='') {
    5262         $this->color = $aColor;
    5263         $this->negcolor = $aNegcolor;
    5264     }
    5265 
    5266     function SetFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=8) {
    5267         $this->ff=$aFontFamily;
    5268         $this->fs=$aFontStyle;
    5269         $this->fsize=$aFontSize;
     4850        $this->show=$aFlag;
     4851    }
     4852
     4853    function SetColor($aColor,$aNegcolor="") {
     4854        $this->color = $aColor;
     4855        $this->negcolor = $aNegcolor;
     4856    }
     4857
     4858    function SetFont($aFontFamily,$aFontStyle=FS_NORMAL,$aFontSize=10) {
     4859        $this->ff=$aFontFamily;
     4860        $this->fs=$aFontStyle;
     4861        $this->fsize=$aFontSize;
    52704862    }
    52714863
    52724864    function ApplyFont($aImg) {
    5273         $aImg->SetFont($this->ff,$this->fs,$this->fsize);
     4865        $aImg->SetFont($this->ff,$this->fs,$this->fsize);
    52744866    }
    52754867
    52764868    function SetMargin($aMargin) {
    5277         $this->margin = $aMargin;
     4869        $this->margin = $aMargin;
    52784870    }
    52794871
    52804872    function SetAngle($aAngle) {
    5281         $this->angle = $aAngle;
     4873        $this->angle = $aAngle;
    52824874    }
    52834875
    52844876    function SetAlign($aHAlign,$aVAlign='') {
    5285         $this->halign = $aHAlign;
    5286         $this->valign = $aVAlign;
    5287     }
    5288 
    5289     function SetFormat($aFormat,$aNegFormat='') {
    5290         $this->format= $aFormat;
    5291         $this->negformat= $aNegFormat;
     4877        $this->halign = $aHAlign;
     4878        $this->valign = $aVAlign;
     4879    }
     4880
     4881    function SetFormat($aFormat,$aNegFormat="") {
     4882        $this->format= $aFormat;
     4883        $this->negformat= $aNegFormat;
    52924884    }
    52934885
    52944886    function SetFormatCallback($aFunc) {
    5295         $this->iFormCallback = $aFunc;
     4887        $this->iFormCallback = $aFunc;
    52964888    }
    52974889
    52984890    function HideZero($aFlag=true) {
    5299         $this->iHideZero=$aFlag;
     4891        $this->iHideZero=$aFlag;
    53004892    }
    53014893
    53024894    function Stroke($img,$aVal,$x,$y) {
    5303 
    5304         if( $this->show )
    5305         {
    5306             if( $this->negformat=='' ) {
    5307                 $this->negformat=$this->format;
    5308             }
    5309             if( $this->negcolor=='' ) {
    5310                 $this->negcolor=$this->color;
    5311             }
    5312 
    5313             if( $aVal===NULL || (is_string($aVal) && ($aVal=='' || $aVal=='-' || $aVal=='x' ) ) ) {
    5314                 return;
    5315             }
    5316 
    5317             if( is_numeric($aVal) && $aVal==0 && $this->iHideZero ) {
    5318                 return;
    5319             }
    5320 
    5321             // Since the value is used in different cirumstances we need to check what
    5322             // kind of formatting we shall use. For example, to display values in a line
    5323             // graph we simply display the formatted value, but in the case where the user
    5324             // has already specified a text string we don't fo anything.
    5325             if( $this->iFormCallback != '' ) {
    5326                 $f = $this->iFormCallback;
    5327                 $sval = call_user_func($f,$aVal);
    5328             }
    5329             elseif( is_numeric($aVal) ) {
    5330                 if( $aVal >= 0 ) {
    5331                     $sval=sprintf($this->format,$aVal);
    5332                 }
    5333                 else {
    5334                     $sval=sprintf($this->negformat,$aVal);
    5335                 }
    5336             }
    5337             else {
    5338                 $sval=$aVal;
    5339             }
    5340 
    5341             $y = $y-sign($aVal)*$this->margin;
    5342 
    5343             $this->txt->Set($sval);
    5344             $this->txt->SetPos($x,$y);
    5345             $this->txt->SetFont($this->ff,$this->fs,$this->fsize);
    5346             if( $this->valign == '' ) {
    5347                 if( $aVal >= 0 ) {
    5348                     $valign = "bottom";
    5349                 }
    5350                 else {
    5351                     $valign = "top";
    5352                 }
    5353             }
    5354             else {
    5355                 $valign = $this->valign;
    5356             }
    5357             $this->txt->Align($this->halign,$valign);
    5358 
    5359             $this->txt->SetOrientation($this->angle);
    5360             if( $aVal > 0 ) {
    5361                 $this->txt->SetColor($this->color);
    5362             }
    5363             else {
    5364                 $this->txt->SetColor($this->negcolor);
    5365             }
    5366             $this->txt->Stroke($img);
    5367         }
     4895       
     4896        if( $this->show )
     4897        {
     4898            if( $this->negformat=="" ) $this->negformat=$this->format;
     4899            if( $this->negcolor=="" ) $this->negcolor=$this->color;
     4900
     4901            if( $aVal===NULL || (is_string($aVal) && ($aVal=="" || $aVal=="-" || $aVal=="x" ) ) )
     4902                return;
     4903
     4904            if( is_numeric($aVal) && $aVal==0 && $this->iHideZero ) {
     4905                return;
     4906            }
     4907
     4908            // Since the value is used in different cirumstances we need to check what
     4909            // kind of formatting we shall use. For example, to display values in a line
     4910            // graph we simply display the formatted value, but in the case where the user
     4911            // has already specified a text string we don't fo anything.
     4912            if( $this->iFormCallback != '' ) {
     4913                $f = $this->iFormCallback;
     4914                $sval = call_user_func($f,$aVal);
     4915            }
     4916            elseif( is_numeric($aVal) ) {
     4917                if( $aVal >= 0 )
     4918                    $sval=sprintf($this->format,$aVal);
     4919                else
     4920                    $sval=sprintf($this->negformat,$aVal);
     4921            }
     4922            else
     4923                $sval=$aVal;
     4924
     4925            $y = $y-sign($aVal)*$this->margin;
     4926
     4927            $txt = new Text($sval,$x,$y);
     4928            $txt->SetFont($this->ff,$this->fs,$this->fsize);
     4929            if( $this->valign == "" ) {
     4930                if( $aVal >= 0 )
     4931                    $valign = "bottom";
     4932                else
     4933                    $valign = "top";
     4934            }
     4935            else
     4936                $valign = $this->valign;
     4937            $txt->Align($this->halign,$valign);
     4938
     4939            $txt->SetOrientation($this->angle);
     4940            if( $aVal > 0 )
     4941                $txt->SetColor($this->color);
     4942            else
     4943                $txt->SetColor($this->negcolor);
     4944            $txt->Stroke($img);
     4945        }
    53684946    }
    53694947}
     
    53784956    public $legend='';
    53794957    public $coords=array();
    5380     public $color='black';
     4958    public $color="black";
    53814959    public $hidelegend=false;
    53824960    public $line_weight=1;
    53834961    public $csimtargets=array(),$csimwintargets=array(); // Array of targets for CSIM
    5384     public $csimareas='';   // Resultant CSIM area tags
    5385     public $csimalts=null;   // ALT:s for corresponding target
     4962    public $csimareas="";                       // Resultant CSIM area tags     
     4963    public $csimalts=null;                      // ALT:s for corresponding target
    53864964    public $legendcsimtarget='',$legendcsimwintarget='';
    53874965    public $legendcsimalt='';
    5388     protected $weight=1;
     4966    protected $weight=1;       
    53894967    protected $center=false;
    5390 
    5391     protected $inputValues;
    5392     protected $isRunningClear = false;
    5393 
    5394     function __construct($aDatay,$aDatax=false) {
    5395         $this->numpoints = count($aDatay);
    5396         if( $this->numpoints==0 ) {
    5397             JpGraphError::RaiseL(25121);//("Empty input data array specified for plot. Must have at least one data point.");
    5398         }
    5399 
    5400         if (!$this->isRunningClear) {
    5401             $this->inputValues = array();
    5402             $this->inputValues['aDatay'] = $aDatay;
    5403             $this->inputValues['aDatax'] = $aDatax;
    5404         }
    5405 
    5406         $this->coords[0]=$aDatay;
    5407         if( is_array($aDatax) ) {
    5408             $this->coords[1]=$aDatax;
    5409             $n = count($aDatax);
    5410             for( $i=0; $i < $n; ++$i ) {
    5411                 if( !is_numeric($aDatax[$i]) ) {
    5412                     JpGraphError::RaiseL(25070);
    5413                 }
    5414             }
    5415         }
    5416         $this->value = new DisplayValue();
    5417     }
     4968//---------------
     4969// CONSTRUCTOR
     4970    function Plot($aDatay,$aDatax=false) {
     4971        $this->numpoints = count($aDatay);
     4972        if( $this->numpoints==0 )
     4973            JpGraphError::RaiseL(25121);//("Empty input data array specified for plot. Must have at least one data point.");
     4974        $this->coords[0]=$aDatay;
     4975        if( is_array($aDatax) ) {
     4976            $this->coords[1]=$aDatax;
     4977            $n = count($aDatax);
     4978            for($i=0; $i < $n; ++$i ) {
     4979                if( !is_numeric($aDatax[$i]) ) {
     4980                    JpGraphError::RaiseL(25070);
     4981                }
     4982            }
     4983        }
     4984        $this->value = new DisplayValue();
     4985    }
     4986
     4987//---------------
     4988// PUBLIC METHODS       
    54184989
    54194990    // Stroke the plot
     
    54214992    // the subclasses
    54224993    function Stroke($aImg,$aXScale,$aYScale) {
    5423         JpGraphError::RaiseL(25122);//("JpGraph: Stroke() must be implemented by concrete subclass to class Plot");
     4994        JpGraphError::RaiseL(25122);//("JpGraph: Stroke() must be implemented by concrete subclass to class Plot");
    54244995    }
    54254996
    54264997    function HideLegend($f=true) {
    5427         $this->hidelegend = $f;
     4998        $this->hidelegend = $f;
    54284999    }
    54295000
    54305001    function DoLegend($graph) {
    5431         if( !$this->hidelegend )
    5432         $this->Legend($graph);
     5002        if( !$this->hidelegend )
     5003            $this->Legend($graph);
    54335004    }
    54345005
    54355006    function StrokeDataValue($img,$aVal,$x,$y) {
    5436         $this->value->Stroke($img,$aVal,$x,$y);
    5437     }
    5438 
    5439     // Set href targets for CSIM
     5007        $this->value->Stroke($img,$aVal,$x,$y);
     5008    }
     5009       
     5010    // Set href targets for CSIM       
    54405011    function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') {
    5441         $this->csimtargets=$aTargets;
    5442         $this->csimwintargets=$aWinTargets;
    5443         $this->csimalts=$aAlts;
    5444     }
    5445 
     5012        $this->csimtargets=$aTargets;
     5013        $this->csimwintargets=$aWinTargets;
     5014        $this->csimalts=$aAlts;         
     5015    }
     5016       
    54465017    // Get all created areas
    54475018    function GetCSIMareas() {
    5448         return $this->csimareas;
    5449     }
    5450 
     5019        return $this->csimareas;
     5020    }   
     5021       
    54515022    // "Virtual" function which gets called before any scale
    54525023    // or axis are stroked used to do any plot specific adjustment
    54535024    function PreStrokeAdjust($aGraph) {
    5454         if( substr($aGraph->axtype,0,4) == "text" && (isset($this->coords[1])) ) {
    5455             JpGraphError::RaiseL(25123);//("JpGraph: You can't use a text X-scale with specified X-coords. Use a \"int\" or \"lin\" scale instead.");
    5456         }
    5457         return true;
    5458     }
    5459 
    5460     // Virtual function to the the concrete plot class to make any changes to the graph
    5461     // and scale before the stroke process begins
    5462     function PreScaleSetup($aGraph) {
    5463         // Empty
    5464     }
    5465 
     5025        if( substr($aGraph->axtype,0,4) == "text" && (isset($this->coords[1])) )
     5026            JpGraphError::RaiseL(25123);//("JpGraph: You can't use a text X-scale with specified X-coords. Use a \"int\" or \"lin\" scale instead.");
     5027        return true;   
     5028    }
     5029       
    54665030    // Get minimum values in plot
    54675031    function Min() {
    5468         if( isset($this->coords[1]) ) {
    5469             $x=$this->coords[1];
    5470         }
    5471         else {
    5472             $x='';
    5473         }
    5474         if( $x != '' && count($x) > 0 ) {
    5475             $xm=min($x);
    5476         }
    5477         else {
    5478             $xm=0;
    5479         }
    5480         $y=$this->coords[0];
    5481         $cnt = count($y);
    5482         if( $cnt > 0 ) {
    5483             $i=0;
    5484             while( $i<$cnt && !is_numeric($ym=$y[$i]) ) {
    5485                 $i++;
    5486             }
    5487             while( $i < $cnt) {
    5488                 if( is_numeric($y[$i]) ) {
    5489                     $ym=min($ym,$y[$i]);
    5490                 }
    5491                 ++$i;
    5492             }
    5493         }
    5494         else {
    5495             $ym='';
    5496         }
    5497         return array($xm,$ym);
    5498     }
    5499 
     5032        if( isset($this->coords[1]) )
     5033            $x=$this->coords[1];
     5034        else
     5035            $x="";
     5036        if( $x != "" && count($x) > 0 ) {
     5037            $xm=min($x);
     5038        }
     5039        else
     5040            $xm=0;
     5041        $y=$this->coords[0];
     5042        $cnt = count($y);
     5043        if( $cnt > 0 ) {
     5044            /*
     5045            if( ! isset($y[0]) ) {
     5046                JpGraphError('The input data array must have consecutive values from position 0 and forward. The given y-array starts with empty values (NULL)');
     5047            }
     5048            $ym = $y[0];
     5049            */
     5050            $i=0;
     5051            while( $i<$cnt && !is_numeric($ym=$y[$i]) )
     5052                $i++;
     5053            while( $i < $cnt) {
     5054                if( is_numeric($y[$i]) )
     5055                    $ym=min($ym,$y[$i]);
     5056                ++$i;
     5057            }                   
     5058        }
     5059        else
     5060            $ym="";
     5061        return array($xm,$ym);
     5062    }
     5063       
    55005064    // Get maximum value in plot
    55015065    function Max() {
    5502         if( isset($this->coords[1]) ) {
    5503             $x=$this->coords[1];
    5504         }
    5505         else {
    5506             $x='';
    5507         }
    5508 
    5509         if( $x!='' && count($x) > 0 ) {
    5510             $xm=max($x);
    5511         }
    5512         else {
    5513             $xm = $this->numpoints-1;
    5514         }
    5515         $y=$this->coords[0];
    5516         if( count($y) > 0 ) {
    5517             $cnt = count($y);
    5518             $i=0;
    5519             while( $i<$cnt && !is_numeric($ym=$y[$i]) ) {
    5520                 $i++;
    5521             }
    5522             while( $i < $cnt ) {
    5523                 if( is_numeric($y[$i]) ) {
    5524                     $ym=max($ym,$y[$i]);
    5525                 }
    5526                 ++$i;
    5527             }
    5528         }
    5529         else {
    5530             $ym='';
    5531         }
    5532         return array($xm,$ym);
    5533     }
    5534 
     5066        if( isset($this->coords[1]) )
     5067            $x=$this->coords[1];
     5068        else
     5069            $x="";
     5070
     5071        if( $x!="" && count($x) > 0 )
     5072            $xm=max($x);
     5073        else {
     5074            $xm = $this->numpoints-1;
     5075        }
     5076        $y=$this->coords[0];
     5077        if( count($y) > 0 ) {
     5078            /*
     5079            if( !isset($y[0]) ) {
     5080                JpGraphError::Raise('The input data array must have consecutive values from position 0 and forward. The given y-array starts with empty values (NULL)');
     5081//              $y[0] = 0;
     5082// Change in 1.5.1 Don't treat this as an error any more. Just silently convert to 0
     5083// Change in 1.17 Treat his as an error again !! This is the right way to do !!
     5084            }
     5085            */
     5086            $cnt = count($y);
     5087            $i=0;
     5088            while( $i<$cnt && !is_numeric($ym=$y[$i]) )
     5089                $i++;                           
     5090            while( $i < $cnt ) {
     5091                if( is_numeric($y[$i]) )
     5092                    $ym=max($ym,$y[$i]);
     5093                ++$i;
     5094            }
     5095        }
     5096        else
     5097            $ym="";
     5098        return array($xm,$ym);
     5099    }
     5100       
    55355101    function SetColor($aColor) {
    5536         $this->color=$aColor;
    5537     }
    5538 
     5102        $this->color=$aColor;
     5103    }
     5104       
    55395105    function SetLegend($aLegend,$aCSIM='',$aCSIMAlt='',$aCSIMWinTarget='') {
    5540         $this->legend = $aLegend;
    5541         $this->legendcsimtarget = $aCSIM;
    5542         $this->legendcsimwintarget = $aCSIMWinTarget;
    5543         $this->legendcsimalt = $aCSIMAlt;
     5106        $this->legend = $aLegend;
     5107        $this->legendcsimtarget = $aCSIM;
     5108        $this->legendcsimwintarget = $aCSIMWinTarget;
     5109        $this->legendcsimalt = $aCSIMAlt;
    55445110    }
    55455111
    55465112    function SetWeight($aWeight) {
    5547         $this->weight=$aWeight;
    5548     }
    5549 
     5113        $this->weight=$aWeight;
     5114    }
     5115               
    55505116    function SetLineWeight($aWeight=1) {
    5551         $this->line_weight=$aWeight;
    5552     }
    5553 
     5117        $this->line_weight=$aWeight;
     5118    }
     5119       
    55545120    function SetCenter($aCenter=true) {
    5555         $this->center = $aCenter;
    5556     }
    5557 
     5121        $this->center = $aCenter;
     5122    }
     5123       
    55585124    // This method gets called by Graph class to plot anything that should go
    55595125    // into the margin after the margin color has been set.
    55605126    function StrokeMargin($aImg) {
    5561         return true;
     5127        return true;
    55625128    }
    55635129
    55645130    // Framework function the chance for each plot class to set a legend
    55655131    function Legend($aGraph) {
    5566         if( $this->legend != '' ) {
    5567             $aGraph->legend->Add($this->legend,$this->color,'',0,$this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    5568         }
    5569     }
    5570 
    5571     function Clear() {
    5572         $this->isRunningClear = true;
    5573         $this->__construct($this->inputValues['aDatay'], $this->inputValues['aDatax']);
    5574         $this->isRunningClear = false;
    5575     }
    5576 
     5132        if( $this->legend != "" )
     5133            $aGraph->legend->Add($this->legend,$this->color,"",0,$this->legendcsimtarget,
     5134                                 $this->legendcsimalt,$this->legendcsimwintarget);   
     5135    }
     5136       
    55775137} // Class
    55785138
    55795139
    5580 // Provide a deterministic list of new colors whenever the getColor() method
    5581 // is called. Used to automatically set colors of plots.
    5582 class ColorFactory {
    5583 
    5584     static private $iIdx = 0;
    5585     static private $iColorList = array(
    5586         'black',
    5587         'blue',
    5588         'orange',
    5589         'darkgreen',
    5590         'red',
    5591         'AntiqueWhite3',
    5592         'aquamarine3',
    5593         'azure4',
    5594         'brown',
    5595         'cadetblue3',
    5596         'chartreuse4',
    5597         'chocolate',
    5598         'darkblue',
    5599         'darkgoldenrod3',
    5600         'darkorchid3',
    5601         'darksalmon',
    5602         'darkseagreen4',
    5603         'deepskyblue2',
    5604         'dodgerblue4',
    5605         'gold3',
    5606         'hotpink',
    5607         'lawngreen',
    5608         'lightcoral',
    5609         'lightpink3',
    5610         'lightseagreen',
    5611         'lightslateblue',
    5612         'mediumpurple',
    5613         'olivedrab',
    5614         'orangered1',
    5615         'peru',
    5616         'slategray',
    5617         'yellow4',
    5618         'springgreen2');
    5619     static private $iNum = 33;
    5620 
    5621     static function getColor() {
    5622         if( ColorFactory::$iIdx >= ColorFactory::$iNum )
    5623             ColorFactory::$iIdx = 0;
    5624         return ColorFactory::$iColorList[ColorFactory::$iIdx++];
    5625     }
    5626 
     5140//===================================================
     5141// CLASS PlotLine
     5142// Description:
     5143// Data container class to hold properties for a static
     5144// line that is drawn directly in the plot area.
     5145// Usefull to add static borders inside a plot to show
     5146// for example set-values
     5147//===================================================
     5148class PlotLine {
     5149    public $scaleposition, $direction=-1;
     5150    protected $weight=1;
     5151    protected $color="black";
     5152    private $legend='',$hidelegend=false, $legendcsimtarget='', $legendcsimalt='',$legendcsimwintarget='';
     5153    private $iLineStyle='solid';
     5154
     5155//---------------
     5156// CONSTRUCTOR
     5157    function PlotLine($aDir=HORIZONTAL,$aPos=0,$aColor="black",$aWeight=1) {
     5158        $this->direction = $aDir;
     5159        $this->color=$aColor;
     5160        $this->weight=$aWeight;
     5161        $this->scaleposition=$aPos;
     5162    }
     5163       
     5164//---------------
     5165// PUBLIC METHODS       
     5166
     5167    function SetLegend($aLegend,$aCSIM='',$aCSIMAlt='',$aCSIMWinTarget='') {
     5168        $this->legend = $aLegend;
     5169        $this->legendcsimtarget = $aCSIM;
     5170        $this->legendcsimwintarget = $aCSIMWinTarget;
     5171        $this->legendcsimalt = $aCSIMAlt;
     5172    }
     5173
     5174    function HideLegend($f=true) {
     5175        $this->hidelegend = $f;
     5176    }
     5177
     5178    function SetPosition($aScalePosition) {
     5179        $this->scaleposition=$aScalePosition;
     5180    }
     5181       
     5182    function SetDirection($aDir) {
     5183        $this->direction = $aDir;
     5184    }
     5185       
     5186    function SetColor($aColor) {
     5187        $this->color=$aColor;
     5188    }
     5189       
     5190    function SetWeight($aWeight) {
     5191        $this->weight=$aWeight;
     5192    }
     5193
     5194    function SetLineStyle($aStyle) {
     5195        $this->iLineStyle = $aStyle;
     5196    }
     5197
     5198//---------------
     5199// PRIVATE METHODS
     5200
     5201    function DoLegend(&$graph) {
     5202        if( !$this->hidelegend )
     5203            $this->Legend($graph);
     5204    }
     5205
     5206    // Framework function the chance for each plot class to set a legend
     5207    function Legend(&$aGraph) {
     5208        if( $this->legend != "" ) {
     5209            $dummyPlotMark = new PlotMark();
     5210            $lineStyle = 1;
     5211            $aGraph->legend->Add($this->legend,$this->color,$dummyPlotMark,$lineStyle,
     5212                                 $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);   
     5213        }
     5214    }
     5215
     5216    function PreStrokeAdjust($aGraph) {
     5217        // Nothing to do
     5218    }
     5219       
     5220    function Stroke($aImg,$aXScale,$aYScale) {
     5221        $aImg->SetColor($this->color);
     5222        $aImg->SetLineWeight($this->weight);   
     5223        $oldStyle = $aImg->SetLineStyle($this->iLineStyle);
     5224        if( $this->direction == VERTICAL ) {
     5225            $ymin_abs=$aYScale->Translate($aYScale->GetMinVal());
     5226            $ymax_abs=$aYScale->Translate($aYScale->GetMaxVal());
     5227            $xpos_abs=$aXScale->Translate($this->scaleposition);
     5228            $aImg->StyleLine($xpos_abs, $ymin_abs, $xpos_abs, $ymax_abs);
     5229        }
     5230        elseif( $this->direction == HORIZONTAL ) {
     5231            $xmin_abs=$aXScale->Translate($aXScale->GetMinVal());
     5232            $xmax_abs=$aXScale->Translate($aXScale->GetMaxVal());
     5233            $ypos_abs=$aYScale->Translate($this->scaleposition);
     5234            $aImg->StyleLine($xmin_abs, $ypos_abs, $xmax_abs, $ypos_abs);
     5235        }
     5236        else {
     5237            JpGraphError::RaiseL(25125);//(" Illegal direction for static line");
     5238        }
     5239        $aImg->SetLineStyle($oldStyle);
     5240    }
    56275241}
    56285242
  • trunk/client/modules/Elezioni/grafici/jpgraph_antispam-digits.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_ANTISPAM.PHP
    4 // Description: Genarate anti-spam challenge
    5 // Created:     2004-10-07
    6 // Ver:         $Id: jpgraph_antispam-digits.php 1930 2010-01-22 20:19:27Z ljp $
     3// File:        JPGRAPH_ANTISPAM.PHP
     4// Description: Genarate anti-spam challenge
     5// Created:     2004-10-07
     6// Ver:         $Id: jpgraph_antispam-digits.php 781 2006-10-08 08:07:47Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    1313    public $iHeight=30, $iWidth=30;
    1414
    15     function __construct() {
    16         //==========================================================
    17         // d6-small.jpg
    18         //==========================================================
    19         $this->digits['6'][0]= 645 ;
    20         $this->digits['6'][1]=
    21      '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    22      'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
    23      'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'.
    24      'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'.
    25      'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'.
    26      'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'.
    27      'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'.
    28      'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'.
    29      'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ;
    30 
    31         //==========================================================
    32         // d2-small.jpg
    33         //==========================================================
    34         $this->digits['2'][0]= 606 ;
    35         $this->digits['2'][1]=
    36      '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    37      'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
    38      'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'.
    39      'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'.
    40      'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'.
    41      'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'.
    42      'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'.
    43      '7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'.
    44      'DLZ6f//Z' ;
    45 
    46         //==========================================================
    47         // d9-small.jpg
    48         //==========================================================
    49         $this->digits['9'][0]= 680 ;
    50         $this->digits['9'][1]=
    51      '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    52      'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
    53      'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'.
    54      'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'.
    55      'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'.
    56      'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'.
    57      'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'.
    58      'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'.
    59      'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'.
    60      '1V1//9k=' ;
    61 
    62         //==========================================================
    63         // d5-small.jpg
    64         //==========================================================
    65         $this->digits['5'][0]= 632 ;
    66         $this->digits['5'][1]=
    67      '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    68      'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
    69      'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'.
    70      'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'.
    71      'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'.
    72      'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'.
    73      'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'.
    74      'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'.
    75      '8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ;
    76 
    77         //==========================================================
    78         // d1-small.jpg
    79         //==========================================================
    80         $this->digits['1'][0]= 646 ;
    81         $this->digits['1'][1]=
    82      '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    83      'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
    84      'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'.
    85      'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'.
    86      'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'.
    87      'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'.
    88      'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'.
    89      'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'.
    90      'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ;
    91 
    92         //==========================================================
    93         // d8-small.jpg
    94         //==========================================================
    95         $this->digits['8'][0]= 694 ;
    96         $this->digits['8'][1]=
    97      '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    98      'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
    99      'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'.
    100      'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'.
    101      'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'.
    102      'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'.
    103      '44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'.
    104      'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'.
    105      'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'.
    106      'EylmLHQltptPZKQOBo1FzH//2Q==' ;
    107 
    108         //==========================================================
    109         // d4-small.jpg
    110         //==========================================================
    111         $this->digits['4'][0]= 643 ;
    112         $this->digits['4'][1]=
    113      '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    114      'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
    115      'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'.
    116      'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'.
    117      'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'.
    118      'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'.
    119      'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'.
    120      '27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'.
    121      'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ;
    122 
    123         //==========================================================
    124         // d7-small.jpg
    125         //==========================================================
    126         $this->digits['7'][0]= 658 ;
    127         $this->digits['7'][1]=
    128      '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    129      'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
    130      'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'.
    131      'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'.
    132      'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'.
    133      '19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'.
    134      'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'.
    135      '8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'.
    136      'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ;
    137 
    138         //==========================================================
    139         // d3-small.jpg
    140         //==========================================================
    141         $this->digits['3'][0]= 662 ;
    142         $this->digits['3'][1]=
    143      '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    144      'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
    145      'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'.
    146      'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'.
    147      'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'.
    148      'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'.
    149      'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'.
    150      'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'.
    151      'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ;
     15    function HandDigits() {
     16//==========================================================
     17// d6-small.jpg
     18//==========================================================
     19        $this->digits['6'][0]= 645 ;
     20        $this->digits['6'][1]=
     21            '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
     22            'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     23            'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAEBAAMBAAAAAAAAAAAAAAAABgMEBwX/xAAvEAABAwMC'.
     24            'BAQEBwAAAAAAAAABAgMEAAURBiESIjFRBxMUQRUWMmFTYnGRkrHC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFhEBAQEAAAAA'.
     25            'AAAAAAAAAAAAAAER/9oADAMBAAIRAxEAPwDslwiR3oDku8ONttsAvDiVyMcO/ET7ke5/aoOz6k1Vr5htNjW7a7M1yO3NTQU9JUDu'.
     26            'GgrlSn8xyf6p4gXaHJvNps9/mKZtSkGdMjRwpfqAFBLLACRlZUrJONsI2717No1lbZ10kx7XGnRpKWQ/6GVGMfzEJ5VFIVtsOH6e'.
     27            'wyKVhYsia0y22pLThSkJK1uniVgdThOM0ol+StIUhpopIyCFq3H8aUVCwnG3PGe4Rp6fLXJtMdyM0ojcIWvIz3HFnAPfrWTXb6GN'.
     28            'WaLXDwZjVz8pKEfhuIUFg/bAz9sVJ61nt61mxJFslLtq7e5yPqiBT4UDklKw4MDpt+u+9bFiu9riXNu83R+fcr6tohuQ5HQhmK37'.
     29            'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ;
     30
     31//==========================================================
     32// d2-small.jpg
     33//==========================================================
     34        $this->digits['2'][0]= 606 ;
     35        $this->digits['2'][1]=
     36            '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
     37            'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     38            'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEQMBIgACEQEDEQH/xAAYAAEBAQEBAAAAAAAAAAAAAAAFAAQHAv/EACsQAAEDBAEC'.
     39            'BAYDAAAAAAAAAAIBAwQABQYRIRIxQVFhcQcTFSJSU5GU0f/EABcBAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAZEQACAwEAAAAAAAAA'.
     40            'AAAAAAAAARESUUH/2gAMAwEAAhEDEQA/AOqXm/Q8dxmOL4PPSnCSNFixx6nXnkXgRT3Te17JWbGsveueSyLZdbPItNxOKLzTLjou'.
     41            'gYCSoSoY8ISKSbFeUrzkdlnTL1YshskiErkQnFEZaF8kkdBBVdjyi6RNL5+9F486eS/ECVkcBtDt1vZcho5viS8ZCp9C9tAIAm/F'.
     42            'VoPRU+HRtJ5JVRP1kP0PfwP+1VKrHBMliXG4Nw8VgE4xGkuqk2S1wTUNEVdIvgpL9iL6KtNxY7WOwo9tt0RCitj0sR2uCbFPPzH1'.
     43            '7+6rRuSRcljMBMsUy2tky045KOawZk5xtEFBJEROO3hx61kh2rPCIX3MhsyC4QmfTbC6lH8dq5212qwkiG5H6Y/9R2qm+ofxqqsL'.
     44            'DLZ6f//Z' ;
     45
     46//==========================================================
     47// d9-small.jpg
     48//==========================================================
     49        $this->digits['9'][0]= 680 ;
     50        $this->digits['9'][1]=
     51            '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
     52            'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     53            'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwP/xAArEAABAwMD'.
     54            'AgYBBQAAAAAAAAABAgMEBQYRABIhE1EUIjEzQUIHMlJhcdH/xAAWAQEBAQAAAAAAAAAAAAAAAAACAQD/xAAYEQEAAwEAAAAAAAAA'.
     55            'AAAAAAAAAREhQf/aAAwDAQACEQMRAD8AkK7brF6X7XpMeGoKhFMLEeT4ZUheEhanF4OcZ2pTgDykk92bZpdCsi7aezLjxkIPUZiV'.
     56            'RSCy8hah7EkZ27yM7V+iscal5bE22Lon1qNDmSKROd8Sl+Ix1lMOlIS4HGgQpbStoUCnlJz8HmsXtW3Lst2rmBAelLMRRekOwnYz'.
     57            'Edls9QKKnOVLyk7UgcbzzrdBthqEJJwZbAI4x1U/7o1TaFa9lG36aXaZTy54VrcXUgrzsGdx+T30aNydweqVw1GS87T6Lb86Q4ha'.
     58            'my/IAYjZBx+snKk99oOQMf1AViE65SY348hzFy6hPKnqtKz7DC1lbqyPrvJKUJ7H+M6Wrt3InP7o1brFNp4bCDGhxGAsqz69VSiQ'.
     59            'ORwBxrrQ7itm1ac7Hp0WoGTIc3PSn0pccdcP2WorycfA1RaRHjxosZqOyhtDTSAhCf2gDAGjVHTd9sKSCumynFEZK1tIJUe58/ro'.
     60            '1V1//9k=' ;
     61
     62//==========================================================
     63// d5-small.jpg
     64//==========================================================
     65        $this->digits['5'][0]= 632 ;
     66        $this->digits['5'][1]=
     67            '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
     68            'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     69            'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgIFBwT/xAAoEAABAwME'.
     70            'AQQCAwAAAAAAAAABAgMEBQYRABIhIkEUMVFhBxNCgaH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAv/EABcRAQEBAQAAAAAAAAAAAAAA'.
     71            'AAABEUH/2gAMAwEAAhEDEQA/ANGvW4YVOeiRX5b4mv5Sin05IdlupPKdo/j2SO3+6TbPNQvOsTVz33KRT4csR3YUF7Dsh5OSFvug'.
     72            'kqG4FPBxnjxpvvi4KZb1pTpU+QwxUi2Y7ZIAefUk5ATxnB9/gbtL/wCH1UpuhPUlZlMVaQ0mS8zJjqZOPfc2TwpIUonI9tw40R1r'.
     73            'WNGq/wBdJR1XT3lqHBUnGCfkfWjRWs1ve249erQqQYjOtN1FqPUpCXQ4WIzQSsJwT0UpRwQPG0nzqyuNHobjsl9kBuWqoOoXtT1/'.
     74            'WppZcA8lKRj64HxqU+3KpAr6plElRVKef3S4E0K9O8pLXVzKcqSsJAB9wSAca6bSoNXeuA1+5pEV+SGFNU1iKVFqI0Vdx2AJUeoz'.
     75            '8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ;
     76
     77//==========================================================
     78// d1-small.jpg
     79//==========================================================
     80        $this->digits['1'][0]= 646 ;
     81        $this->digits['1'][1]=
     82            '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
     83            'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     84            'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEwMBIgACEQEDEQH/xAAZAAADAAMAAAAAAAAAAAAAAAAABQYCBAf/xAApEAACAQMD'.
     85            'AwQBBQAAAAAAAAABAgMEBREABiESMUEHEyJRkSNCYXGB/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/8QAFxEBAQEBAAAAAAAAAAAA'.
     86            'AAAAAAEREv/aAAwDAQACEQMRAD8A6jdd4WLbstILnc4Uq0VoWpkJknb6IjXLHJUePOlez923fcW4r1SxWlqC2UbdKirQif3Xw3yA'.
     87            'OFAGT09/kO3OmV3a20MFRf6lIYPcpy7yRRAzgxjIy2M8YwcdiBzpX6d22VNvUlTXsFkuwkrKqNSfnK7F8OTzwrAY+l5zoxKskudN'.
     88            'EgQPUT9PBkWF3DH+1GPxo1mLnRoAqF2VRgGOFmX/AAgY/GjRUP6hVMFv2FuFqUvUGrpDFJMBnpdyF5bsAQew7Hxzp6LZNT0yQ1DI'.
     89            'wp0QCFBhD0jCsfLZHxbx5xxpTuvb1+v9PV7Ztk9roLPLCjmSSN3mX5ZwqjCgZX7PfWxDQb2in96pv9qq46aTE0bW4x9ceAWAYPwS'.
     90            'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ;
     91
     92//==========================================================
     93// d8-small.jpg
     94//==========================================================
     95        $this->digits['8'][0]= 694 ;
     96        $this->digits['8'][1]=
     97            '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
     98            'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     99            'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AFQMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABgcEBf/EACsQAAEDAwMD'.
     100            'AwMFAAAAAAAAAAECAwQFBhEAEiEUMVEHE0EVYYEiIzJCsf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/EABcRAQEBAQAAAAAAAAAA'.
     101            'AAAAAAABERL/2gAMAwEAAhEDEQA/AKL6gVVUa0i1T5QjvTprUJMlxW4R9zgQXe/AH+kaWrntqlWjaq7gpcmotXAw82ht9yY4tch8'.
     102            'uAFC0k7VBXPGMY51ruiaue+bThIj+7NbWqS+7HDxajFf6AlB/k44o8ZOABk4xkL0X0tZiojKrlRuGRJjugqldSlKGf6t7BuUQe3J'.
     103            '44xxxrA1a4KVJipLidri8uLHgqOcfjOPxo0o2hdDvS1CmV2Yl6fS5ioipIQR1CAlKkLKR2UUqAI8g6NRSwuuyHab6s1ufLI/Zai7'.
     104            'UBJOxhTS0+6B32pWSFH4CidOdWU0ukLiN1BLr0zG5Sdm3GRvcPhIT858DvjXNrVsSLnm/VIdTXS6tTnFsxZTSN3jchaTwps+O/z9'.
     105            'tcBVq3hIX0tYqlIiQHdy5CqRHKHXEjAOMgBKjnvyRk4xrQa7OiGt1K5biYZL8SoVEpjOqkFsONtJCNwASeCQrn7aNUKnQYtLp7EC'.
     106            'EylmLHQltptPZKQOBo1FzH//2Q==' ;
     107
     108//==========================================================
     109// d4-small.jpg
     110//==========================================================
     111        $this->digits['4'][0]= 643 ;
     112        $this->digits['4'][1]=
     113            '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
     114            'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     115            'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAAABAYHAv/EAC0QAAIBAwQA'.
     116            'BAMJAAAAAAAAAAECAwQFEQAGEiETFDFBUmGBByIjUVNxobHR/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAIB/8QAGBEBAAMBAAAAAAAA'.
     117            'AAAAAAAAAAERIVH/2gAMAwEAAhEDEQA/ANjM00Nxmt1xiWW31CZp5uJwoAAaOQ/n7qfcZHqO5my3q5XX7R6ijiqnNut9u4NyJ4yv'.
     118            'JJyjYr8Xhrn5g599J7x3ulBNU7Zo7dXXXcLQ8kURYi4epYtkALjOePv1nUvbLvV7P3BZm3DR3eh88Kp7pVzBZI6iUhGWRRGWwE44'.
     119            'HX3V+uiL1uHgt+vL/H+aNJQ3CSeCOaFqSaJ1DJKs/TqRkMOvQjvRorHE4pRDLNWLGlRHGUeYIORXs9e5B7OP31E0fmdyb/t0DJ4Q'.
     120            '27bfx3YZzPUIoAAz7IpOD6cuxq0uNumqLfVNDOqXBoZEjnZcqhIPXH4c46+WkdoWOltu3IDDLLLVVR83UVcuPEmmcZZ2/rHoAANG'.
     121            'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ;
     122
     123//==========================================================
     124// d7-small.jpg
     125//==========================================================
     126        $this->digits['7'][0]= 658 ;
     127        $this->digits['7'][1]=
     128            '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
     129            'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     130            'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABgEFBwT/xAAuEAABAwIE'.
     131            'BAQGAwAAAAAAAAABAgMEBREABiExEhMiQSMyUXEHFBclVJFhk9L/xAAXAQADAQAAAAAAAAAAAAAAAAAAAQID/8QAGREBAQEAAwAA'.
     132            'AAAAAAAAAAAAAAEREiFR/9oADAMBAAIRAxEAPwDXq9mCjZeQ05VZ5ZST4bfEpa3VdglCbqUe+g9MZ5Uq7V8415WXoMSdQ6etgSps'.
     133            '19wpkCMDZKUpv0FZvbi1NzpYasMDLDUbMVXrtQdbeeU23xLWkj5RlLYK0J7anW9gbAjCzkOtsVSUJUdtc6dVZK51UeaFm4LKbhpC'.
     134            'l7EhIFkDW974GbRI2XorUVls1OTdKAOqUpR0Hc3198GITQ6k+hLwrEpoODiDenRfW23bBicg78JXxPpD0mgVOW5PAivNNpahsPW5'.
     135            '8xxQaSVkboQnhsnYm5OHqDGp1IpsalMKjMsMIC3+XZKbJFth62/QOEfMOZqZXp9JcKZTcGmTky3meSi7xQklI81vMR+sXIz/AEgp'.
     136            'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ;
     137
     138//==========================================================
     139// d3-small.jpg
     140//==========================================================
     141        $this->digits['3'][0]= 662 ;
     142        $this->digits['3'][1]=
     143            '/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
     144            'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     145            'MjIyMjIyMjIyMjIyMjIyMjIyMv/AABEIAB4AEgMBIgACEQEDEQH/xAAZAAACAwEAAAAAAAAAAAAAAAAABAUGBwL/xAArEAABBAED'.
     146            'AwMDBQEAAAAAAAABAgMEBREABhIhMUEiMmETFZEHFkJDUdH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/xAAYEQEBAQEBAAAAAAAA'.
     147            'AAAAAAAAEQExQf/aAAwDAQACEQMRAD8A0vclruBdk3VVLLUNssGRJsZSCtqOjlgJAHvcOD6c4HnOdIbcttw1W5P29cFEhuawqTXS'.
     148            'VsJjnCMBxKkJJx7goAde+ceJfdNxU0UNlyymyXHi6kxWUNl1S3EnkAEIHX2nv86qtTuZr9Q9+1VhRsOoYpYcgSVyAE/TdewkJxnK'.
     149            'sBCjkdPGpnOtFMd3PqsXgfOAgD8Y0aX+11H9rDDjn8lr9yj5J+dGqsqxaw6Cc9cQZU4Sp7zTJsIrKlcUEKwhSin1JABI45GUjqOu'.
     150            'lbOvjbc3Ts9ynjGCy445UuFLYRzbWgrT6fhSCQSMDke+pew2zYVly/d7YchNqkMJZnQpgV9J8IzwWFJyUrAJHYgjvpLbu37G5nR7'.
     151            'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ;
     152    }
     153}
     154
     155class AntiSpam {
     156
     157    var $iNumber='';
     158
     159    function AntiSpam($aNumber='') {
     160        $this->iNumber = $aNumber;
     161    }
     162
     163    function Rand($aLen) {
     164        $d='';
     165        for($i=0; $i < $aLen; ++$i) {
     166            $d .= rand(1,9);
     167        }
     168        $this->iNumber = $d;
     169        return $d;
     170    }
     171
     172    function Stroke() {
     173
     174        $n=strlen($this->iNumber);
     175        for($i=0; $i < $n; ++$i ) {
     176            if( !is_numeric($this->iNumber[$i]) || $this->iNumber[$i]==0 ) {
     177                return false;
     178            }
     179        }
     180
     181        $dd = new HandDigits();
     182        $n = strlen($this->iNumber);
     183        $img = @imagecreatetruecolor($n*$dd->iWidth, $dd->iHeight);
     184        if( $img < 1 ) {
     185            return false;
     186        }
     187        $start=0;
     188        for($i=0; $i < $n; ++$i ) {
     189            $size = $dd->digits[$this->iNumber[$i]][0];
     190            $dimg = imagecreatefromstring(base64_decode($dd->digits[$this->iNumber[$i]][1]));
     191            imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $dd->iHeight);
     192            $start += imagesx($dimg);
     193        }
     194        $resimg = @imagecreatetruecolor($start+4, $dd->iHeight+4);
     195        if( $resimg < 1 ) {
     196            return false;
     197        }
     198        imagecopy($resimg,$img,2,2,0,0,$start, $dd->iHeight);
     199        header("Content-type: image/jpeg");
     200        imagejpeg($resimg);
     201        return true;
    152202    }
    153203}
    154204
    155 class AntiSpam {
    156 
    157     private $iNumber='';
    158 
    159     function __construct($aNumber='') {
    160         $this->iNumber = $aNumber;
    161     }
    162 
    163     function Rand($aLen) {
    164         $d='';
    165         for($i=0; $i < $aLen; ++$i) {
    166             $d .= rand(1,9);
    167         }
    168         $this->iNumber = $d;
    169         return $d;
    170     }
    171 
    172     function Stroke() {
    173 
    174         $n=strlen($this->iNumber);
    175         for($i=0; $i < $n; ++$i ) {
    176             if( !is_numeric($this->iNumber[$i]) || $this->iNumber[$i]==0 ) {
    177                 return false;
    178             }
    179         }
    180 
    181         $dd = new HandDigits();
    182         $n = strlen($this->iNumber);
    183         $img = @imagecreatetruecolor($n*$dd->iWidth, $dd->iHeight);
    184         if( $img < 1 ) {
    185             return false;
    186         }
    187         $start=0;
    188         for($i=0; $i < $n; ++$i ) {
    189             $size = $dd->digits[$this->iNumber[$i]][0];
    190             $dimg = imagecreatefromstring(base64_decode($dd->digits[$this->iNumber[$i]][1]));
    191             imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $dd->iHeight);
    192             $start += imagesx($dimg);
    193         }
    194         $resimg = @imagecreatetruecolor($start+4, $dd->iHeight+4);
    195         if( $resimg < 1 ) {
    196             return false;
    197         }
    198         imagecopy($resimg,$img,2,2,0,0,$start, $dd->iHeight);
    199         header("Content-type: image/jpeg");
    200         imagejpeg($resimg);
    201         return true;
    202     }
    203 }
    204 
    205205?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_antispam.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_ANTISPAM.PHP
    4 // Description: Genarate anti-spam challenge
    5 // Created:     2004-10-07
    6 // Ver:         $Id: jpgraph_antispam.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        JPGRAPH_ANTISPAM.PHP
     4// Description: Genarate anti-spam challenge
     5// Created:     2004-10-07
     6// Ver:         $Id: jpgraph_antispam.php 808 2006-11-28 19:10:40Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    1313    public $iHeight=30, $iWidth=30;
    1414
    15     function __construct() {
    16 
    17         //==========================================================
    18         // lj-small.jpg
    19         //==========================================================
    20         $this->chars['j'][0]= 658 ;
    21         $this->chars['j'][1]=
     15    function HandDigits() {
     16
     17//==========================================================
     18// lj-small.jpg
     19//==========================================================
     20$this->chars['j'][0]= 658 ;
     21$this->chars['j'][1]=
    2222'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    2323'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    3030'cEgeNHhi7D3qC3UN69M8tIakRhgrh9o748+eNGtcCiKjjpkQKlMTEg3ZwoxtHHtgfTRpYXArvp//2Q==' ;
    3131
    32         //==========================================================
    33         // lf-small.jpg
    34         //==========================================================
    35         $this->chars['f'][0]= 633 ;
    36         $this->chars['f'][1]=
     32//==========================================================
     33// lf-small.jpg
     34//==========================================================
     35$this->chars['f'][0]= 633 ;
     36$this->chars['f'][1]=
    3737'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    3838'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    4545'4+mjUrURyrUNMZFEkkIOFuFAbsP9d/OjVIQ6Vh4tP//Z' ;
    4646
    47         //==========================================================
    48         // lb-small.jpg
    49         //==========================================================
    50         $this->chars['b'][0]= 645 ;
    51         $this->chars['b'][1]=
     47//==========================================================
     48// lb-small.jpg
     49//==========================================================
     50$this->chars['b'][0]= 645 ;
     51$this->chars['b'][1]=
    5252'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    5353'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    6060'8AcU3UzFuhUSBFud6nRXoz96mqmJZWg7m2dqUNhWBwdqQSP1UU5c/FFCn//Z' ;
    6161
    62         //==========================================================
    63         // d6-small.jpg
    64         //==========================================================
    65         $this->chars['6'][0]= 645 ;
    66         $this->chars['6'][1]=
     62//==========================================================
     63// d6-small.jpg
     64//==========================================================
     65$this->chars['6'][0]= 645 ;
     66$this->chars['6'][1]=
    6767'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    6868'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    7575'paaC8DruScmg6X8KkjZEhbaB9KEyFYSOw26Uqd+e7Qerl5z74DY/1SomP//Z' ;
    7676
    77         //==========================================================
    78         // lx-small.jpg
    79         //==========================================================
    80         $this->chars['x'][0]= 650 ;
    81         $this->chars['x'][1]=
     77//==========================================================
     78// lx-small.jpg
     79//==========================================================
     80$this->chars['x'][0]= 650 ;
     81$this->chars['x'][1]=
    8282'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    8383'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    9090'uKgwqtTZDTMOU0FttqRkoHggnPkEEHRrkJ6t1SlSHYUOc6zHaWrsbQrATk5/vRqK/9k=' ;
    9191
    92         //==========================================================
    93         // d2-small.jpg
    94         //==========================================================
    95         $this->chars['2'][0]= 606 ;
    96         $this->chars['2'][1]=
     92//==========================================================
     93// d2-small.jpg
     94//==========================================================
     95$this->chars['2'][0]= 606 ;
     96$this->chars['2'][1]=
    9797'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    9898'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    105105'DLZ6f//Z' ;
    106106
    107         //==========================================================
    108         // lm-small.jpg
    109         //==========================================================
    110         $this->chars['m'][0]= 649 ;
    111         $this->chars['m'][1]=
     107//==========================================================
     108// lm-small.jpg
     109//==========================================================
     110$this->chars['m'][0]= 649 ;
     111$this->chars['m'][1]=
    112112'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    113113'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    120120'jg2zf50W9zk524GAEihuz+xbIOD82jW5TkjtRPZkTkJ+4VgDhQfuj/f3OjUxl1f/2Q==' ;
    121121
    122         //==========================================================
    123         // lt-small.jpg
    124         //==========================================================
    125         $this->chars['t'][0]= 648 ;
    126         $this->chars['t'][1]=
     122//==========================================================
     123// lt-small.jpg
     124//==========================================================
     125$this->chars['t'][0]= 648 ;
     126$this->chars['t'][1]=
    127127'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    128128'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    135135'D46EnuD+6Nc1smDNrTlRkxqtMo1vzKhIdYgU9YDqVpISrLhHxSSd21I0aYyqP//Z' ;
    136136
    137         //==========================================================
    138         // li-small.jpg
    139         //==========================================================
    140         $this->chars['i'][0]= 639 ;
    141         $this->chars['i'][1]=
     137//==========================================================
     138// li-small.jpg
     139//==========================================================
     140$this->chars['i'][0]= 639 ;
     141$this->chars['i'][1]=
    142142'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    143143'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    149149'Yf8AOl7JTdw5eOCz0jw3+LbYCfA9nz71msb8KMxoTGTw+5srjsipAdDqFBQBIuiOl6KrdYyJMyTCshlw2G3Fr/HiNqNNAqJJUoGl'.
    150150'KND+h47km1bZwsvCbYYjycxIyK1qDv2yEi0hQviK8atKDcy9j//Z' ;
    151 
    152 
    153         //==========================================================
    154         // lp-small.jpg
    155         //==========================================================
    156         $this->chars['p'][0]= 700 ;
    157         $this->chars['p'][1]=
     151 
     152
     153//==========================================================
     154// lp-small.jpg
     155//==========================================================
     156$this->chars['p'][0]= 700 ;
     157$this->chars['p'][1]=
    158158'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    159159'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    167167'C5LwAyq2EtpHZI7mxPYDRqoctdESimz/2Q==' ;
    168168
    169         //==========================================================
    170         // le-small.jpg
    171         //==========================================================
    172         $this->chars['e'][0]= 700 ;
    173         $this->chars['e'][1]=
     169//==========================================================
     170// le-small.jpg
     171//==========================================================
     172$this->chars['e'][0]= 700 ;
     173$this->chars['e'][1]=
    174174'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    175175'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    183183'LBNF6qrzG6t0spEu6+fpL7YMXhUndp//2Q==' ;
    184184
    185         //==========================================================
    186         // la-small.jpg
    187         //==========================================================
    188         $this->chars['a'][0]= 730 ;
    189         $this->chars['a'][1]=
     185//==========================================================
     186// la-small.jpg
     187//==========================================================
     188$this->chars['a'][0]= 730 ;
     189$this->chars['a'][1]=
    190190'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    191191'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    199199'HVDtXStE5K5jlPU7PF3Q41+okJFkjgC+3OuNSYiSzHaLtRcW4UDMpLYSCbakDW3thhum5p//2Q==' ;
    200200
    201         //==========================================================
    202         // d9-small.jpg
    203         //==========================================================
    204         $this->chars['9'][0]= 680 ;
    205         $this->chars['9'][1]=
     201//==========================================================
     202// d9-small.jpg
     203//==========================================================
     204$this->chars['9'][0]= 680 ;
     205$this->chars['9'][1]=
    206206'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    207207'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    215215'1V1//9k=' ;
    216216
    217         //==========================================================
    218         // d5-small.jpg
    219         //==========================================================
    220         $this->chars['5'][0]= 632 ;
    221         $this->chars['5'][1]=
     217//==========================================================
     218// d5-small.jpg
     219//==========================================================
     220$this->chars['5'][0]= 632 ;
     221$this->chars['5'][1]=
    222222'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    223223'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    230230'8DGlTDwG3CAf3q/pI0ah6MDhLz6U+EpXwPoaNMU//9k=' ;
    231231
    232         //==========================================================
    233         // d1-small.jpg
    234         //==========================================================
    235         $this->chars['1'][0]= 646 ;
    236         $this->chars['1'][1]=
     232//==========================================================
     233// d1-small.jpg
     234//==========================================================
     235$this->chars['1'][0]= 646 ;
     236$this->chars['1'][1]=
    237237'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    238238'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    245245'PsYzoixgmheBGjIVcYCnjp/jHjHbRpe1JLn9OnopE/a0ykvjwDx47aNMXqP/2Q==' ;
    246246
    247         //==========================================================
    248         // ll-small.jpg
    249         //==========================================================
    250         $this->chars['l'][0]= 626 ;
    251         $this->chars['l'][1]=
     247//==========================================================
     248// ll-small.jpg
     249//==========================================================
     250$this->chars['l'][0]= 626 ;
     251$this->chars['l'][1]=
    252252'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    253253'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    261261
    262262
    263         //==========================================================
    264         // ls-small.jpg
    265         //==========================================================
    266         $this->chars['s'][0]= 701 ;
    267         $this->chars['s'][1]=
     263//==========================================================
     264// ls-small.jpg
     265//==========================================================
     266$this->chars['s'][0]= 701 ;
     267$this->chars['s'][1]=
    268268'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    269269'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    277277'lymUOLdWfJyoHA+gA7AAAaNPE3ysJdLT/9k=' ;
    278278
    279         //==========================================================
    280         // lh-small.jpg
    281         //==========================================================
    282         $this->chars['h'][0]= 677 ;
    283         $this->chars['h'][1]=
     279//==========================================================
     280// lh-small.jpg
     281//==========================================================
     282$this->chars['h'][0]= 677 ;
     283$this->chars['h'][1]=
    284284'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    285285'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    294294
    295295
    296         //==========================================================
    297         // ld-small.jpg
    298         //==========================================================
    299         $this->chars['d'][0]= 681 ;
    300         $this->chars['d'][1]=
     296//==========================================================
     297// ld-small.jpg
     298//==========================================================
     299$this->chars['d'][0]= 681 ;
     300$this->chars['d'][1]=
    301301'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    302302'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    310310'Ia1JX//Z' ;
    311311
    312         //==========================================================
    313         // d8-small.jpg
    314         //==========================================================
    315         $this->chars['8'][0]= 694 ;
    316         $this->chars['8'][1]=
     312//==========================================================
     313// d8-small.jpg
     314//==========================================================
     315$this->chars['8'][0]= 694 ;
     316$this->chars['8'][1]=
    317317'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    318318'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    326326'EylmLHQltptPZKQOBo1FzH//2Q==' ;
    327327
    328         //==========================================================
    329         // lz-small.jpg
    330         //==========================================================
    331         $this->chars['z'][0]= 690 ;
    332         $this->chars['z'][1]=
     328//==========================================================
     329// lz-small.jpg
     330//==========================================================
     331$this->chars['z'][0]= 690 ;
     332$this->chars['z'][1]=
    333333'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    334334'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    342342'KrnsKH06I/rVrQKkf//Z' ;
    343343
    344         //==========================================================
    345         // d4-small.jpg
    346         //==========================================================
    347         $this->chars['4'][0]= 643 ;
    348         $this->chars['4'][1]=
     344//==========================================================
     345// d4-small.jpg
     346//==========================================================
     347$this->chars['4'][0]= 643 ;
     348$this->chars['4'][1]=
    349349'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    350350'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    357357'GI7KIY1ijoLeEQBVCwIoAHpgY6Hy0aZe7mJ2jeHLKcEhusj6aNKgzr//2Q==' ;
    358358
    359         //==========================================================
    360         // lv-small.jpg
    361         //==========================================================
    362         $this->chars['v'][0]= 648 ;
    363         $this->chars['v'][1]=
     359//==========================================================
     360// lv-small.jpg
     361//==========================================================
     362$this->chars['v'][0]= 648 ;
     363$this->chars['v'][1]=
    364364'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    365365'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    372372'ubmMBCVJdjx0pRyLoWR4I8aNIQ8BvZMNtMTeUcsptKfc4tC1gAkCyFC+K0aJtf/Z' ;
    373373
    374         //==========================================================
    375         // lk-small.jpg
    376         //==========================================================
    377         $this->chars['k'][0]= 680 ;
    378         $this->chars['k'][1]=
     374//==========================================================
     375// lk-small.jpg
     376//==========================================================
     377$this->chars['k'][0]= 680 ;
     378$this->chars['k'][1]=
    379379'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    380380'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    388388'k9aP/9k=' ;
    389389
    390         //==========================================================
    391         // lr-small.jpg
    392         //==========================================================
    393         $this->chars['r'][0]= 681 ;
    394         $this->chars['r'][1]=
     390//==========================================================
     391// lr-small.jpg
     392//==========================================================
     393$this->chars['r'][0]= 681 ;
     394$this->chars['r'][1]=
    395395'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    396396'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    404404'ZeKZ1//Z' ;
    405405
    406         //==========================================================
    407         // lg-small.jpg
    408         //==========================================================
    409         $this->chars['g'][0]= 655 ;
    410         $this->chars['g'][1]=
     406//==========================================================
     407// lg-small.jpg
     408//==========================================================
     409$this->chars['g'][0]= 655 ;
     410$this->chars['g'][1]=
    411411'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    412412'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    419419'4ywltanVJvuJI+RQs/sHRqy2r003JhsImEc/CUyhxRZBjKV2oJ8eRXNmufPnRo1WIz3DdNn/2Q==' ;
    420420
    421         //==========================================================
    422         // lc-small.jpg
    423         //==========================================================
    424         $this->chars['c'][0]= 629 ;
    425         $this->chars['c'][1]=
     421//==========================================================
     422// lc-small.jpg
     423//==========================================================
     424$this->chars['c'][0]= 629 ;
     425$this->chars['c'][1]=
    426426'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    427427'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    434434'3Ls3TqNs5Hc9h23w49NWL9K+Q/VD5T/zhwPH/9k=' ;
    435435
    436         //==========================================================
    437         // d7-small.jpg
    438         //==========================================================
    439         $this->chars['7'][0]= 658 ;
    440         $this->chars['7'][1]=
     436//==========================================================
     437// d7-small.jpg
     438//==========================================================
     439$this->chars['7'][0]= 658 ;
     440$this->chars['7'][1]=
    441441'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    442442'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    449449'Q0qPNu6ea8Q2jqtbp8+2w9h/OKORc/cpHjt1dDSHOtLZ4ekHW23bBjj+o9H/AB539aP94MG0+L//2Q==' ;
    450450
    451         //==========================================================
    452         // ly-small.jpg
    453         //==========================================================
    454         $this->chars['y'][0]= 672 ;
    455         $this->chars['y'][1]=
     451//==========================================================
     452// ly-small.jpg
     453//==========================================================
     454$this->chars['y'][0]= 672 ;
     455$this->chars['y'][1]=
    456456'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    457457'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    464464'uvmXdlme6n4dCwlRBKEgA2tj99QG7Ilncp5QqpU31PMsJ6x7A32f6SPxo0hPVCD45oVyKf0MtgeT97/nRrO7UOCFla3tn//Z' ;
    465465
    466         //==========================================================
    467         // d3-small.jpg
    468         //==========================================================
    469         $this->chars['3'][0]= 662 ;
    470         $this->chars['3'][1]=
     466//==========================================================
     467// d3-small.jpg
     468//==========================================================
     469$this->chars['3'][0]= 662 ;
     470$this->chars['3'][1]=
    471471'/9j/4AAQSkZJRgABAQEASgBKAAD//gAJSnBHcmFwaP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg'.
    472472'IiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    479479'vck5C3YRKYEOEVJZj8kjKypXqWvirjk9h+dB9i4faa89TDZUfKlIyT8k+To10a6KTkpcJ/0vL/7o0TS//9k=' ;
    480480
    481         //==========================================================
    482         // ln-small.jpg
    483         //==========================================================
    484         $this->chars['n'][0]= 643 ;
    485         $this->chars['n'][1]=
     481//==========================================================
     482// ln-small.jpg
     483//==========================================================
     484$this->chars['n'][0]= 643 ;
     485$this->chars['n'][1]=
    486486'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    487487'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    494494'5+WNAh5ZCu/r2+dGrgq0pi0DhmlRsSSAfqMd+b6ZyNu3po1Rk1yNBe3/2Q==' ;
    495495
    496         //==========================================================
    497         // lu-small.jpg
    498         //==========================================================
    499         $this->chars['u'][0]= 671 ;
    500         $this->chars['u'][1]=
     496//==========================================================
     497// lu-small.jpg
     498//==========================================================
     499$this->chars['u'][0]= 671 ;
     500$this->chars['u'][1]=
    501501'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    502502'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    509509'jT7Xc74HtOYnHyUOh8yWUvKeHhy0CiPVUAPoDRrm+OeznTva6lzsyMjCYbbaiNJjJSWElagD5tRpNUSALFeNGoOCH7Bv/9k=' ;
    510510
    511         //==========================================================
    512         // lw-small.jpg
    513         //==========================================================
    514         $this->chars['w'][0]= 673 ;
    515         $this->chars['w'][1]=
     511//==========================================================
     512// lw-small.jpg
     513//==========================================================
     514$this->chars['w'][0]= 673 ;
     515$this->chars['w'][1]=
    516516'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    517517'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    524524'Rsn+tVpiyJnqv09YfOXu5AycgZZQEhBZjgDBOOgwO/po0sttWHdNzqLruioa4UwmdaC3kYp4IwSvJlBHKQ4OSe3po0qxM6P/2Q==' ;
    525525
    526         //==========================================================
    527         // lq-small.jpg
    528         //==========================================================
    529         $this->chars['q'][0]= 671 ;
    530         $this->chars['q'][1]=
     526//==========================================================
     527// lq-small.jpg
     528//==========================================================
     529$this->chars['q'][0]= 671 ;
     530$this->chars['q'][1]=
    531531'/9j/4AAQSkZJRgABAQEASgBKAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx'.
    532532'NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy'.
     
    541541
    542542
     543    }
     544}
     545
     546class AntiSpam {
     547
     548    private $iData='';
     549    private $iDD=null;
     550
     551    function AntiSpam($aData='') {
     552        $this->iData = $aData;
     553        $this->iDD = new HandDigits(); 
     554    }
     555
     556    function Set($aData) {
     557        $this->iData = $aData;
     558    }
     559
     560    function Rand($aLen) {
     561        $d='';
     562        for($i=0; $i < $aLen; ++$i) {
     563            if( rand(0,9) < 6 ) {
     564                // Digits
     565                $d .= chr( ord('1') + rand(0,8) );
     566            }
     567            else {
     568                // Letters
     569                do {
     570                    $offset = rand(0,25);
     571                } while ( $offset==14 );
     572                $d .= chr( ord('a') + $offset );
     573            }
     574        }
     575        $this->iData = $d;
     576        return $d;
     577    }
     578
     579    function Stroke() {
     580
     581        $n=strlen($this->iData);
     582        if( $n==0 ) {
     583            return false;
     584        }
     585
     586        for($i=0; $i < $n; ++$i ) {
     587            if( $this->iData[$i]==='0' || strtolower($this->iData[$i])==='o') {
     588                return false;
     589            }
     590        }
     591
     592        $img = @imagecreatetruecolor($n*$this->iDD->iWidth, $this->iDD->iHeight);
     593        if( $img < 1 ) {
     594            return false;
     595        }
     596
     597        $start=0;
     598        for($i=0; $i < $n; ++$i ) {
     599            $dimg = imagecreatefromstring(base64_decode($this->iDD->chars[strtolower($this->iData[$i])][1]));
     600            imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $this->iDD->iHeight);
     601            $start += imagesx($dimg);
     602        }
     603        $resimg = @imagecreatetruecolor($start+4, $this->iDD->iHeight+4);
     604        if( $resimg < 1 ) {
     605            return false;
     606        }
     607
     608        imagecopy($resimg,$img,2,2,0,0,$start, $this->iDD->iHeight);
     609        header("Content-type: image/jpeg");
     610        imagejpeg($resimg);
     611        return true;
    543612    }
    544613}
    545614
    546 class AntiSpam {
    547 
    548     private $iData='';
    549     private $iDD=null;
    550 
    551     function __construct($aData='') {
    552         $this->iData = $aData;
    553         $this->iDD = new HandDigits();
    554     }
    555 
    556     function Set($aData) {
    557         $this->iData = $aData;
    558     }
    559 
    560     function Rand($aLen) {
    561         $d='';
    562         for($i=0; $i < $aLen; ++$i) {
    563             if( rand(0,9) < 6 ) {
    564                 // Digits
    565                 $d .= chr( ord('1') + rand(0,8) );
    566             }
    567             else {
    568                 // Letters
    569                 do {
    570                     $offset = rand(0,25);
    571                 } while ( $offset==14 );
    572                 $d .= chr( ord('a') + $offset );
    573             }
    574         }
    575         $this->iData = $d;
    576         return $d;
    577     }
    578 
    579     function Stroke() {
    580 
    581         $n=strlen($this->iData);
    582         if( $n==0 ) {
    583             return false;
    584         }
    585 
    586         for($i=0; $i < $n; ++$i ) {
    587             if( $this->iData[$i]==='0' || strtolower($this->iData[$i])==='o') {
    588                 return false;
    589             }
    590         }
    591 
    592         $img = @imagecreatetruecolor($n*$this->iDD->iWidth, $this->iDD->iHeight);
    593         if( $img < 1 ) {
    594             return false;
    595         }
    596 
    597         $start=0;
    598         for($i=0; $i < $n; ++$i ) {
    599             $dimg = imagecreatefromstring(base64_decode($this->iDD->chars[strtolower($this->iData[$i])][1]));
    600             imagecopy($img,$dimg,$start,0,0,0,imagesx($dimg), $this->iDD->iHeight);
    601             $start += imagesx($dimg);
    602         }
    603         $resimg = @imagecreatetruecolor($start+4, $this->iDD->iHeight+4);
    604         if( $resimg < 1 ) {
    605             return false;
    606         }
    607 
    608         imagecopy($resimg,$img,2,2,0,0,$start, $this->iDD->iHeight);
    609         header("Content-type: image/jpeg");
    610         imagejpeg($resimg);
    611         return true;
    612     }
    613 }
    614 
    615615?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_bar.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_BAR.PHP
    4  // Description: Bar plot extension for JpGraph
    5  // Created:     2001-01-08
    6  // Ver:         $Id: jpgraph_bar.php 1905 2009-10-06 18:00:21Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_BAR.PHP
     4// Description: Bar plot extension for JpGraph
     5// Created:     2001-01-08
     6// Ver:         $Id: jpgraph_bar.php 1017 2008-07-08 06:09:28Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212require_once('jpgraph_plotband.php');
     
    2626//===================================================
    2727// CLASS BarPlot
    28 // Description: Main code to produce a bar plot
     28// Description: Main code to produce a bar plot 
    2929//===================================================
    3030class BarPlot extends Plot {
     
    3737    protected $width=0.4; // in percent of major ticks
    3838    protected $abswidth=-1; // Width in absolute pixels
    39     protected $ybase=0; // Bars start at 0
     39    protected $ybase=0; // Bars start at 0 
    4040    protected $align="center";
    4141    protected $bar_shadow=false;
    4242    protected $bar_shadow_color="black";
    43     protected $bar_shadow_hsize=3,$bar_shadow_vsize=3;
    44     protected $bar_3d=false;
    45     protected $bar_3d_hsize=3,$bar_3d_vsize=3;
    46 
    47     //---------------
    48     // CONSTRUCTOR
    49     function __construct($datay,$datax=false) {
    50         parent::__construct($datay,$datax);
    51         ++$this->numpoints;
    52     }
    53 
    54     //---------------
    55     // PUBLIC METHODS
    56 
     43    protected $bar_shadow_hsize=3,$bar_shadow_vsize=3; 
     44       
     45//---------------
     46// CONSTRUCTOR
     47    function BarPlot($datay,$datax=false) {
     48        $this->Plot($datay,$datax);             
     49        ++$this->numpoints;
     50    }
     51
     52//---------------
     53// PUBLIC METHODS       
     54       
    5755    // Set a drop shadow for the bar (or rather an "up-right" shadow)
    58     function SetShadow($aColor="black",$aHSize=3,$aVSize=3,$aShow=true) {
    59         $this->bar_shadow=$aShow;
    60         $this->bar_shadow_color=$aColor;
    61         $this->bar_shadow_vsize=$aVSize;
    62         $this->bar_shadow_hsize=$aHSize;
    63 
    64         // Adjust the value margin to compensate for shadow
    65         $this->value->margin += $aVSize;
    66     }
    67 
    68     function Set3D($aHSize=3,$aVSize=3,$aShow=true) {
    69         $this->bar_3d=$aShow;
    70         $this->bar_3d_vsize=$aVSize;
    71         $this->bar_3d_hsize=$aHSize;
    72 
    73         $this->value->margin += $aVSize;
    74     }
    75 
     56    function SetShadow($color="black",$hsize=3,$vsize=3,$show=true) {
     57        $this->bar_shadow=$show;
     58        $this->bar_shadow_color=$color;
     59        $this->bar_shadow_vsize=$vsize;
     60        $this->bar_shadow_hsize=$hsize;
     61               
     62        // Adjust the value margin to compensate for shadow
     63        $this->value->margin += $vsize;
     64    }
     65               
    7666    // DEPRECATED use SetYBase instead
    7767    function SetYMin($aYStartValue) {
    78         //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");
    79         $this->ybase=$aYStartValue;
     68        //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");           
     69        $this->ybase=$aYStartValue;
    8070    }
    8171
    8272    // Specify the base value for the bars
    8373    function SetYBase($aYStartValue) {
    84         $this->ybase=$aYStartValue;
    85     }
    86 
    87     // The method will take the specified pattern anre
    88     // return a pattern index that corresponds to the original
    89     // patterm being rotated 90 degreees. This is needed when plottin
    90     // Horizontal bars
    91     function RotatePattern($aPat,$aRotate=true) {
    92         $rotate = array(1 => 2, 2 => 1, 3 => 3, 4 => 5, 5 => 4, 6 => 6, 7 => 7, 8 => 8);
    93         if( $aRotate ) {
    94             return $rotate[$aPat];
    95         }
    96         else {
    97             return $aPat;
    98         }
    99     }
    100 
     74        $this->ybase=$aYStartValue;
     75    }
     76       
    10177    function Legend($graph) {
    102         if( $this->grad && $this->legend!="" && !$this->fill ) {
    103             $color=array($this->grad_fromcolor,$this->grad_tocolor);
    104             // In order to differentiate between gradients and cooors specified as an RGB triple
    105             $graph->legend->Add($this->legend,$color,"",-$this->grad_style,
    106             $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    107         }
    108         elseif( $this->legend!="" && ($this->iPattern > -1 || is_array($this->iPattern)) ) {
    109             if( is_array($this->iPattern) ) {
    110                 $p1 = $this->RotatePattern( $this->iPattern[0], $graph->img->a == 90 );
    111                 $p2 = $this->iPatternColor[0];
    112                 $p3 = $this->iPatternDensity[0];
    113             }
    114             else {
    115                 $p1 = $this->RotatePattern( $this->iPattern, $graph->img->a == 90 );
    116                 $p2 = $this->iPatternColor;
    117                 $p3 = $this->iPatternDensity;
    118             }
    119             if( $p3 < 90 ) $p3 += 5;
    120             $color = array($p1,$p2,$p3,$this->fill_color);
    121             // A kludge: Too mark that we add a pattern we use a type value of < 100
    122             $graph->legend->Add($this->legend,$color,"",-101,
    123                                 $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    124         }
    125         elseif( $this->fill_color && $this->legend!="" ) {
    126             if( is_array($this->fill_color) ) {
    127                 $graph->legend->Add($this->legend,$this->fill_color[0],"",0,
    128                 $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    129             }
    130             else {
    131                 $graph->legend->Add($this->legend,$this->fill_color,"",0,
    132                 $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    133             }
    134         }
     78        if( $this->grad && $this->legend!="" && !$this->fill ) {
     79            $color=array($this->grad_fromcolor,$this->grad_tocolor);
     80            // In order to differentiate between gradients and cooors specified as an RGB triple
     81            $graph->legend->Add($this->legend,$color,"",-$this->grad_style,
     82                                $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     83        }
     84        elseif( $this->legend!="" && ($this->iPattern > -1 || is_array($this->iPattern)) ) {
     85            if( is_array($this->iPattern) ) {
     86                $p1 = $this->iPattern[0];
     87                $p2 = $this->iPatternColor[0];
     88                $p3 = $this->iPatternDensity[0];
     89            }
     90            else {
     91                $p1 = $this->iPattern;
     92                $p2 = $this->iPatternColor;
     93                $p3 = $this->iPatternDensity;
     94            }
     95            $color = array($p1,$p2,$p3,$this->fill_color);
     96            // A kludge: Too mark that we add a pattern we use a type value of < 100
     97            $graph->legend->Add($this->legend,$color,"",-101,
     98                                $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     99        }
     100        elseif( $this->fill_color && $this->legend!="" ) {
     101            if( is_array($this->fill_color) ) {
     102                $graph->legend->Add($this->legend,$this->fill_color[0],"",0,
     103                                    $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     104            }
     105            else {
     106                $graph->legend->Add($this->legend,$this->fill_color,"",0,
     107                                    $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);   
     108            }
     109        }
    135110    }
    136111
    137112    // Gets called before any axis are stroked
    138113    function PreStrokeAdjust($graph) {
    139         parent::PreStrokeAdjust($graph);
    140 
    141         // If we are using a log Y-scale we want the base to be at the
    142         // minimum Y-value unless the user have specifically set some other
    143         // value than the default.
    144         if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 )
    145         $this->ybase = $graph->yaxis->scale->GetMinVal();
    146 
    147         // For a "text" X-axis scale we will adjust the
    148         // display of the bars a little bit.
    149         if( substr($graph->axtype,0,3)=="tex" ) {
    150             // Position the ticks between the bars
    151             $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0);
    152 
    153             // Center the bars
    154             if( $this->abswidth > -1 ) {
    155                 $graph->SetTextScaleAbsCenterOff($this->abswidth);
    156             }
    157             else {
    158                 if( $this->align == "center" )
    159                 $graph->SetTextScaleOff(0.5-$this->width/2);
    160                 elseif( $this->align == "right" )
    161                 $graph->SetTextScaleOff(1-$this->width);
    162             }
    163         }
    164         elseif( ($this instanceof AccBarPlot) || ($this instanceof GroupBarPlot) ) {
    165             // We only set an absolute width for linear and int scale
    166             // for text scale the width will be set to a fraction of
    167             // the majstep width.
    168             if( $this->abswidth == -1 ) {
     114        parent::PreStrokeAdjust($graph);
     115
     116        // If we are using a log Y-scale we want the base to be at the
     117        // minimum Y-value unless the user have specifically set some other
     118        // value than the default.
     119        if( substr($graph->axtype,-3,3)=="log" && $this->ybase==0 )
     120            $this->ybase = $graph->yaxis->scale->GetMinVal();
     121               
     122        // For a "text" X-axis scale we will adjust the
     123        // display of the bars a little bit.
     124        if( substr($graph->axtype,0,3)=="tex" ) {
     125            // Position the ticks between the bars
     126            $graph->xaxis->scale->ticks->SetXLabelOffset(0.5,0);
     127
     128            // Center the bars
     129            if( $this->abswidth > -1 ) {
     130                $graph->SetTextScaleAbsCenterOff($this->abswidth);
     131            }
     132            else {
     133                if( $this->align == "center" )
     134                    $graph->SetTextScaleOff(0.5-$this->width/2);
     135                elseif( $this->align == "right" )
     136                    $graph->SetTextScaleOff(1-$this->width);                   
     137            }
     138        }
     139        elseif( ($this instanceof AccBarPlot) || ($this instanceof GroupBarPlot) ) {
     140            // We only set an absolute width for linear and int scale
     141            // for text scale the width will be set to a fraction of
     142            // the majstep width.
     143            if( $this->abswidth == -1 ) {
    169144                // Not set
    170                 // set width to a visuable sensible default
    171                 $this->abswidth = $graph->img->plotwidth/(2*$this->numpoints);
    172             }
    173         }
     145                // set width to a visuable sensible default
     146                $this->abswidth = $graph->img->plotwidth/(2*$this->numpoints);
     147            }
     148        }
    174149    }
    175150
    176151    function Min() {
    177         $m = parent::Min();
    178         if( $m[1] >= $this->ybase ) $m[1] = $this->ybase;
    179         return $m;
     152        $m = parent::Min();
     153        if( $m[1] >= $this->ybase )
     154            $m[1] = $this->ybase;
     155        return $m;     
    180156    }
    181157
    182158    function Max() {
    183         $m = parent::Max();
    184         if( $m[1] <= $this->ybase ) $m[1] = $this->ybase;
    185         return $m;
    186     }
    187 
     159        $m = parent::Max();
     160        if( $m[1] <= $this->ybase )
     161            $m[1] = $this->ybase;
     162        return $m;     
     163    }   
     164       
    188165    // Specify width as fractions of the major stepo size
    189166    function SetWidth($aWidth) {
    190         if( $aWidth > 1 ) {
    191             // Interpret this as absolute width
    192             $this->abswidth=$aWidth;
    193         }
    194         else {
    195             $this->width=$aWidth;
    196         }
    197     }
    198 
     167        if( $aWidth > 1 ) {
     168            // Interpret this as absolute width
     169            $this->abswidth=$aWidth;
     170        }
     171        else
     172            $this->width=$aWidth;
     173    }
     174       
    199175    // Specify width in absolute pixels. If specified this
    200176    // overrides SetWidth()
    201177    function SetAbsWidth($aWidth) {
    202         $this->abswidth=$aWidth;
    203     }
    204 
     178        $this->abswidth=$aWidth;
     179    }
     180               
    205181    function SetAlign($aAlign) {
    206         $this->align=$aAlign;
    207     }
    208 
     182        $this->align=$aAlign;
     183    }
     184       
    209185    function SetNoFill() {
    210         $this->grad = false;
    211         $this->fill_color=false;
    212         $this->fill=false;
    213     }
    214 
     186        $this->grad = false;
     187        $this->fill_color=false;
     188        $this->fill=false;
     189    }
     190               
    215191    function SetFillColor($aColor) {
    216         // Do an extra error check if the color is specified as an RGB array triple
    217         // In that case convert it to a hex string since it will otherwise be
    218         // interpretated as an array of colors for each individual bar.
    219 
    220         $aColor = RGB::tryHexConversion($aColor);
    221         $this->fill = true ;
    222         $this->fill_color=$aColor;
    223 
    224     }
    225 
     192        $this->fill = true ;
     193        $this->fill_color=$aColor;
     194    }
     195       
    226196    function SetFillGradient($aFromColor,$aToColor=null,$aStyle=null) {
    227         $this->grad = true;
    228         $this->grad_fromcolor = $aFromColor;
    229         $this->grad_tocolor   = $aToColor;
    230         $this->grad_style     = $aStyle;
    231     }
    232 
     197        $this->grad = true;
     198        $this->grad_fromcolor = $aFromColor;
     199        $this->grad_tocolor   = $aToColor;
     200        $this->grad_style     = $aStyle;
     201    }
     202       
    233203    function SetValuePos($aPos) {
    234         $this->valuepos = $aPos;
     204        $this->valuepos = $aPos;
    235205    }
    236206
    237207    function SetPattern($aPattern, $aColor='black'){
    238         if( is_array($aPattern) ) {
    239             $n = count($aPattern);
    240             $this->iPattern = array();
    241             $this->iPatternDensity = array();
    242             if( is_array($aColor) ) {
    243                 $this->iPatternColor = array();
    244                 if( count($aColor) != $n ) {
    245                     JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()');
    246                 }
    247             }
    248             else {
    249                 $this->iPatternColor = $aColor;
    250             }
    251             for( $i=0; $i < $n; ++$i ) {
    252                 $this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]);
    253                 if( is_array($aColor) ) {
    254                     $this->iPatternColor[$i] = $aColor[$i];
    255                 }
    256             }
    257         }
    258         else {
    259             $this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity);
    260             $this->iPatternColor = $aColor;
    261         }
     208        if( is_array($aPattern) ) {
     209            $n = count($aPattern);
     210            $this->iPattern = array();
     211            $this->iPatternDensity = array();
     212            if( is_array($aColor) ) {
     213                $this->iPatternColor = array();
     214                if( count($aColor) != $n ) {
     215                    JpGraphError::RaiseL(2001);//('NUmber of colors is not the same as the number of patterns in BarPlot::SetPattern()');
     216                }
     217            }
     218            else
     219                $this->iPatternColor = $aColor;
     220            for( $i=0; $i < $n; ++$i ) {
     221                $this->_SetPatternHelper($aPattern[$i], $this->iPattern[$i], $this->iPatternDensity[$i]);
     222                if( is_array($aColor) ) {
     223                    $this->iPatternColor[$i] = $aColor[$i];
     224                }
     225            }
     226        }
     227        else {
     228            $this->_SetPatternHelper($aPattern, $this->iPattern, $this->iPatternDensity);
     229            $this->iPatternColor = $aColor;
     230        }
    262231    }
    263232
    264233    function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity){
    265         switch( $aPattern ) {
    266             case PATTERN_DIAG1:
    267                 $aPatternValue= 1;
    268                 $aDensity = 92;
    269                 break;
    270             case PATTERN_DIAG2:
    271                 $aPatternValue= 1;
    272                 $aDensity = 78;
    273                 break;
    274             case PATTERN_DIAG3:
    275                 $aPatternValue= 2;
    276                 $aDensity = 92;
    277                 break;
    278             case PATTERN_DIAG4:
    279                 $aPatternValue= 2;
    280                 $aDensity = 78;
    281                 break;
    282             case PATTERN_CROSS1:
    283                 $aPatternValue= 8;
    284                 $aDensity = 90;
    285                 break;
    286             case PATTERN_CROSS2:
    287                 $aPatternValue= 8;
    288                 $aDensity = 78;
    289                 break;
    290             case PATTERN_CROSS3:
    291                 $aPatternValue= 8;
    292                 $aDensity = 65;
    293                 break;
    294             case PATTERN_CROSS4:
    295                 $aPatternValue= 7;
    296                 $aDensity = 90;
    297                 break;
    298             case PATTERN_STRIPE1:
    299                 $aPatternValue= 5;
    300                 $aDensity = 94;
    301                 break;
    302             case PATTERN_STRIPE2:
    303                 $aPatternValue= 5;
    304                 $aDensity = 85;
    305                 break;
    306             default:
    307                 JpGraphError::RaiseL(2002);
    308                 //('Unknown pattern specified in call to BarPlot::SetPattern()');
    309         }
    310     }
    311 
    312     function Stroke($img,$xscale,$yscale) {
    313 
    314         $numpoints = count($this->coords[0]);
    315         if( isset($this->coords[1]) ) {
    316             if( count($this->coords[1])!=$numpoints ) {
    317                 JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints);
    318             //"Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])."Number of Y-points:$numpoints");
    319             }
    320             else {
    321                 $exist_x = true;
    322             }
    323         }
    324         else {
    325             $exist_x = false;
    326         }
    327 
    328 
    329         $numbars=count($this->coords[0]);
    330 
    331         // Use GetMinVal() instead of scale[0] directly since in the case
    332         // of log scale we get a correct value. Log scales will have negative
    333         // values for values < 1 while still not representing negative numbers.
    334         if( $yscale->GetMinVal() >= 0 )
    335         $zp=$yscale->scale_abs[0];
    336         else {
    337             $zp=$yscale->Translate(0);
    338         }
    339 
    340         if( $this->abswidth > -1 ) {
    341             $abswidth=$this->abswidth;
    342         }
    343         else {
    344             $abswidth=round($this->width*$xscale->scale_factor,0);
    345         }
    346 
    347         // Count pontetial pattern array to avoid doing the count for each iteration
    348         if( is_array($this->iPattern) ) {
    349             $np = count($this->iPattern);
    350         }
    351 
    352         $grad = null;
    353         for($i=0; $i < $numbars; ++$i) {
    354 
    355             // If value is NULL, or 0 then don't draw a bar at all
    356             if ($this->coords[0][$i] === null || $this->coords[0][$i] === '' )
    357             continue;
    358 
    359             if( $exist_x ) {
    360                 $x=$this->coords[1][$i];
    361             }
    362             else {
    363                 $x=$i;
    364             }
    365 
    366             $x=$xscale->Translate($x);
    367 
    368             // Comment Note: This confuses the positioning when using acc together with
    369             // grouped bars. Workaround for fixing #191
    370             /*
    371             if( !$xscale->textscale ) {
    372             if($this->align=="center")
    373             $x -= $abswidth/2;
    374             elseif($this->align=="right")
    375             $x -= $abswidth;
    376             }
    377             */
    378             // Stroke fill color and fill gradient
    379             $pts=array(
    380             $x,$zp,
    381             $x,$yscale->Translate($this->coords[0][$i]),
    382             $x+$abswidth,$yscale->Translate($this->coords[0][$i]),
    383             $x+$abswidth,$zp);
    384             if( $this->grad ) {
    385                 if( $grad === null ) {
    386                     $grad = new Gradient($img);
    387                 }
    388                 if( is_array($this->grad_fromcolor) ) {
    389                     // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array
    390                     // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be
    391                     // an array to specify both (from, to style) for each individual bar. The way to know the difference is
    392                     // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB
    393                     // triple.
    394                     $ng = count($this->grad_fromcolor);
    395                     if( $ng === 3 ) {
    396                         if( is_numeric($this->grad_fromcolor[0]) && $this->grad_fromcolor[0] > 0 && $this->grad_fromcolor[0] < 256 ) {
    397                             // RGB Triple
    398                             $fromcolor = $this->grad_fromcolor;
    399                             $tocolor = $this->grad_tocolor;
    400                             $style = $this->grad_style;
    401                         }
    402                         else {
    403                             $fromcolor = $this->grad_fromcolor[$i % $ng][0];
    404                             $tocolor = $this->grad_fromcolor[$i % $ng][1];
    405                             $style = $this->grad_fromcolor[$i % $ng][2];
    406                         }
    407                     }
    408                     else {
    409                         $fromcolor = $this->grad_fromcolor[$i % $ng][0];
    410                         $tocolor = $this->grad_fromcolor[$i % $ng][1];
    411                         $style = $this->grad_fromcolor[$i % $ng][2];
    412                     }
    413                     $grad->FilledRectangle($pts[2],$pts[3],
    414                                            $pts[6],$pts[7],
    415                                            $fromcolor,$tocolor,$style);
    416                 }
    417                 else {
    418                     $grad->FilledRectangle($pts[2],$pts[3],
    419                     $pts[6],$pts[7],
    420                     $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style);
    421                 }
    422             }
    423             elseif( !empty($this->fill_color) ) {
    424                 if(is_array($this->fill_color)) {
    425                     $img->PushColor($this->fill_color[$i % count($this->fill_color)]);
    426                 } else {
    427                     $img->PushColor($this->fill_color);
    428                 }
    429                 $img->FilledPolygon($pts);
    430                 $img->PopColor();
    431             }
    432 
    433 /////////////////////////kokorahen rectangle polygon//////////////////////
    434 
    435             // Remember value of this bar
    436             $val=$this->coords[0][$i];
    437 
    438             if( !empty($val) && !is_numeric($val) ) {
    439                 JpGraphError::RaiseL(2004,$i,$val);
    440                 //'All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\'');
    441             }
    442 
    443             // Determine the shadow
    444             if( $this->bar_shadow && $val != 0) {
    445 
    446                 $ssh = $this->bar_shadow_hsize;
    447                 $ssv = $this->bar_shadow_vsize;
    448                 // Create points to create a "upper-right" shadow
    449                 if( $val > 0 ) {
    450                     $sp[0]=$pts[6];  $sp[1]=$pts[7];
    451                     $sp[2]=$pts[4];  $sp[3]=$pts[5];
    452                     $sp[4]=$pts[2];  $sp[5]=$pts[3];
    453                     $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
    454                     $sp[8]=$pts[4]+$ssh; $sp[9]=$pts[5]-$ssv;
    455                     $sp[10]=$pts[6]+$ssh; $sp[11]=$pts[7]-$ssv;
    456                 }
    457                 elseif( $val < 0 ) {
    458                     $sp[0]=$pts[4];  $sp[1]=$pts[5];
    459                     $sp[2]=$pts[6];  $sp[3]=$pts[7];
    460                     $sp[4]=$pts[0];  $sp[5]=$pts[1];
    461                     $sp[6]=$pts[0]+$ssh; $sp[7]=$pts[1]-$ssv;
    462                     $sp[8]=$pts[6]+$ssh; $sp[9]=$pts[7]-$ssv;
    463                     $sp[10]=$pts[4]+$ssh; $sp[11]=$pts[5]-$ssv;
    464                 }
    465                 if( is_array($this->bar_shadow_color) ) {
    466                     $numcolors = count($this->bar_shadow_color);
    467                     if( $numcolors == 0 ) {
    468                         JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.');
    469                     }
    470                     $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
    471                 }
    472                 else {
    473                     $img->PushColor($this->bar_shadow_color);
    474                 }
    475                 $img->FilledPolygon($sp);
    476                 $img->PopColor();
    477 
    478             } elseif( $this->bar_3d && $val != 0) {
    479               // Determine the 3D
    480 
    481                 $ssh = $this->bar_3d_hsize;
    482                 $ssv = $this->bar_3d_vsize;
    483 
    484                 // Create points to create a "upper-right" shadow
    485                 if( $val > 0 ) {
    486                     $sp1[0]=$pts[6];  $sp1[1]=$pts[7];
    487                     $sp1[2]=$pts[4];  $sp1[3]=$pts[5];
    488                     $sp1[4]=$pts[4]+$ssh; $sp1[5]=$pts[5]-$ssv;
    489                     $sp1[6]=$pts[6]+$ssh; $sp1[7]=$pts[7]-$ssv;
    490 
    491                     $sp2[0]=$pts[4];  $sp2[1]=$pts[5];
    492                     $sp2[2]=$pts[2];  $sp2[3]=$pts[3];
    493                     $sp2[4]=$pts[2]+$ssh; $sp2[5]=$pts[3]-$ssv;
    494                     $sp2[6]=$pts[4]+$ssh; $sp2[7]=$pts[5]-$ssv;
    495 
    496                 }
    497                 elseif( $val < 0 ) {
    498                     $sp1[0]=$pts[4];  $sp1[1]=$pts[5];
    499                     $sp1[2]=$pts[6];  $sp1[3]=$pts[7];
    500                     $sp1[4]=$pts[6]+$ssh; $sp1[5]=$pts[7]-$ssv;
    501                     $sp1[6]=$pts[4]+$ssh; $sp1[7]=$pts[5]-$ssv;
    502 
    503                     $sp2[0]=$pts[6];  $sp2[1]=$pts[7];
    504                     $sp2[2]=$pts[0];  $sp2[3]=$pts[1];
    505                     $sp2[4]=$pts[0]+$ssh; $sp2[5]=$pts[1]-$ssv;
    506                     $sp2[6]=$pts[6]+$ssh; $sp2[7]=$pts[7]-$ssv;
    507                 }
    508 
    509                 $base_color = $this->fill_color;
    510 
    511                 $img->PushColor($base_color . ':0.7');
    512                 $img->FilledPolygon($sp1);
    513                 $img->PopColor();
    514 
    515                 $img->PushColor($base_color . ':1.1');
    516                 $img->FilledPolygon($sp2);
    517                 $img->PopColor();
    518             }
    519 
    520             // Stroke the pattern
    521             if( is_array($this->iPattern) ) {
    522                 $f = new RectPatternFactory();
    523                 if( is_array($this->iPatternColor) ) {
    524                     $pcolor = $this->iPatternColor[$i % $np];
    525                 }
    526                 else {
    527                     $pcolor = $this->iPatternColor;
    528                 }
    529                 $prect = $f->Create($this->iPattern[$i % $np],$pcolor,1);
    530                 $prect->SetDensity($this->iPatternDensity[$i % $np]);
    531 
    532                 if( $val < 0 ) {
    533                     $rx = $pts[0];
    534                     $ry = $pts[1];
    535                 }
    536                 else {
    537                     $rx = $pts[2];
    538                     $ry = $pts[3];
    539                 }
    540                 $width = abs($pts[4]-$pts[0])+1;
    541                 $height = abs($pts[1]-$pts[3])+1;
    542                 $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
    543                 $prect->Stroke($img);
    544             }
    545             else {
    546                 if( $this->iPattern > -1 ) {
    547                     $f = new RectPatternFactory();
    548                     $prect = $f->Create($this->iPattern,$this->iPatternColor,1);
    549                     $prect->SetDensity($this->iPatternDensity);
    550                     if( $val < 0 ) {
    551                         $rx = $pts[0];
    552                         $ry = $pts[1];
    553                     }
    554                     else {
    555                         $rx = $pts[2];
    556                         $ry = $pts[3];
    557                     }
    558                     $width = abs($pts[4]-$pts[0])+1;
    559                     $height = abs($pts[1]-$pts[3])+1;
    560                     $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
    561                     $prect->Stroke($img);
    562                 }
    563             }
    564 
    565             // Stroke the outline of the bar
    566             if( is_array($this->color) ) {
    567                 $img->SetColor($this->color[$i % count($this->color)]);
    568             }
    569             else {
    570                 $img->SetColor($this->color);
    571             }
    572 
    573             $pts[] = $pts[0];
    574             $pts[] = $pts[1];
    575 
    576             if( $this->weight > 0 ) {
    577                 $img->SetLineWeight($this->weight);
    578                 $img->Polygon($pts);
    579             }
    580 
    581             // Determine how to best position the values of the individual bars
    582             $x=$pts[2]+($pts[4]-$pts[2])/2;
    583             $this->value->SetMargin(5);
    584 
    585             if( $this->valuepos=='top' ) {
    586                 $y=$pts[3];
    587                 if( $img->a === 90 ) {
    588                     if( $val < 0 ) {
    589                         $this->value->SetAlign('right','center');
    590                     }
    591                     else {
    592                         $this->value->SetAlign('left','center');
    593                     }
    594 
    595                 }
    596                 else {
    597                     if( $val < 0 ) {
    598                         $this->value->SetMargin(-5);
    599                         $y=$pts[1];
    600                         $this->value->SetAlign('center','bottom');
    601                     }
    602                     else {
    603                         $this->value->SetAlign('center','bottom');
    604                     }
    605 
    606                 }
    607                 $this->value->Stroke($img,$val,$x,$y);
    608             }
    609             elseif( $this->valuepos=='max' ) {
    610                 $y=$pts[3];
    611                 if( $img->a === 90 ) {
    612                     if( $val < 0 )
    613                     $this->value->SetAlign('left','center');
    614                     else
    615                     $this->value->SetAlign('right','center');
    616                 }
    617                 else {
    618                     if( $val < 0 ) {
    619                         $this->value->SetAlign('center','bottom');
    620                     }
    621                     else {
    622                         $this->value->SetAlign('center','top');
    623                     }
    624                 }
    625                 $this->value->SetMargin(-5);
    626                 $this->value->Stroke($img,$val,$x,$y);
    627             }
    628             elseif( $this->valuepos=='center' ) {
    629                 $y = ($pts[3] + $pts[1])/2;
    630                 $this->value->SetAlign('center','center');
    631                 $this->value->SetMargin(0);
    632                 $this->value->Stroke($img,$val,$x,$y);
    633             }
    634             elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) {
    635                 $y=$pts[1];
    636                 if( $img->a === 90 ) {
    637                     if( $val < 0 )
    638                     $this->value->SetAlign('right','center');
    639                     else
    640                     $this->value->SetAlign('left','center');
    641                 }
    642                 $this->value->SetMargin(3);
    643                 $this->value->Stroke($img,$val,$x,$y);
    644             }
    645             else {
    646                 JpGraphError::RaiseL(2006,$this->valuepos);
    647                 //'Unknown position for values on bars :'.$this->valuepos);
    648             }
    649             // Create the client side image map
    650             $rpts = $img->ArrRotate($pts);
    651             $csimcoord=round($rpts[0]).", ".round($rpts[1]);
    652             for( $j=1; $j < 4; ++$j){
    653                 $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]);
    654             }
    655             if( !empty($this->csimtargets[$i]) ) {
    656                 $this->csimareas .= '<area shape="poly" coords="'.$csimcoord.'" ';
    657                 $this->csimareas .= " href=\"".htmlentities($this->csimtargets[$i])."\"";
    658 
    659                 if( !empty($this->csimwintargets[$i]) ) {
    660                     $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
    661                 }
    662 
    663                 $sval='';
    664                 if( !empty($this->csimalts[$i]) ) {
    665                     $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]);
    666                     $this->csimareas .= " title=\"$sval\" alt=\"$sval\" ";
    667                 }
    668                 $this->csimareas .= " />\n";
    669             }
    670         }
    671         return true;
     234        switch( $aPattern ) {
     235            case PATTERN_DIAG1:
     236                $aPatternValue= 1;
     237                $aDensity = 90;
     238                break;
     239            case PATTERN_DIAG2:
     240                $aPatternValue= 1;
     241                $aDensity = 75;
     242                break;
     243            case PATTERN_DIAG3:
     244                $aPatternValue= 2;
     245                $aDensity = 90;
     246                break;
     247            case PATTERN_DIAG4:
     248                $aPatternValue= 2;
     249                $aDensity = 75;
     250                break;
     251            case PATTERN_CROSS1:
     252                $aPatternValue= 8;
     253                $aDensity = 90;
     254                break;
     255            case PATTERN_CROSS2:
     256                $aPatternValue= 8;
     257                $aDensity = 78;
     258                break;
     259            case PATTERN_CROSS3:
     260                $aPatternValue= 8;
     261                $aDensity = 65;
     262                break;
     263            case PATTERN_CROSS4:
     264                $aPatternValue= 7;
     265                $aDensity = 90;
     266                break;
     267            case PATTERN_STRIPE1:
     268                $aPatternValue= 5;
     269                $aDensity = 90;
     270                break;
     271            case PATTERN_STRIPE2:
     272                $aPatternValue= 5;
     273                $aDensity = 75;
     274                break;
     275            default:
     276                JpGraphError::RaiseL(2002);
     277//('Unknown pattern specified in call to BarPlot::SetPattern()');
     278        }
     279    }
     280
     281    function Stroke($img,$xscale,$yscale) {
     282               
     283        $numpoints = count($this->coords[0]);
     284        if( isset($this->coords[1]) ) {
     285            if( count($this->coords[1])!=$numpoints )
     286                JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints);
     287//"Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])."Number of Y-points:$numpoints");
     288            else
     289                $exist_x = true;
     290        }
     291        else
     292            $exist_x = false;
     293               
     294               
     295        $numbars=count($this->coords[0]);
     296
     297        // Use GetMinVal() instead of scale[0] directly since in the case
     298        // of log scale we get a correct value. Log scales will have negative
     299        // values for values < 1 while still not representing negative numbers.
     300        if( $yscale->GetMinVal() >= 0 )
     301            $zp=$yscale->scale_abs[0];
     302        else {
     303            $zp=$yscale->Translate(0);
     304        }
     305
     306        if( $this->abswidth > -1 ) {
     307            $abswidth=$this->abswidth;
     308        }
     309        else
     310            $abswidth=round($this->width*$xscale->scale_factor,0);
     311
     312        // Count pontetial pattern array to avoid doing the count for each iteration
     313        if( is_array($this->iPattern) ) {
     314            $np = count($this->iPattern);
     315        }
     316                       
     317        $grad = null;
     318        for($i=0; $i < $numbars; ++$i) {
     319
     320            // If value is NULL, or 0 then don't draw a bar at all
     321            if ($this->coords[0][$i] === null || $this->coords[0][$i] === '' )
     322                continue;   
     323
     324            if( $exist_x ) $x=$this->coords[1][$i];
     325            else $x=$i;
     326                       
     327            $x=$xscale->Translate($x);
     328
     329// Comment Note: This confuses the positioning when using acc together with
     330// grouped bars. Workaround for fixing #191
     331/*
     332            if( !$xscale->textscale ) {
     333                if($this->align=="center")
     334                    $x -= $abswidth/2;
     335                elseif($this->align=="right")
     336                    $x -= $abswidth;                   
     337            }
     338*/
     339            // Stroke fill color and fill gradient
     340            $pts=array(
     341                $x,$zp,
     342                $x,$yscale->Translate($this->coords[0][$i]),
     343                $x+$abswidth,$yscale->Translate($this->coords[0][$i]),
     344                $x+$abswidth,$zp);
     345            if( $this->grad ) {
     346                if( $grad === null )
     347                    $grad = new Gradient($img);
     348                if( is_array($this->grad_fromcolor) ) {
     349                    // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array
     350                    // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be
     351                    // an array to specify both (from, to style) for each individual bar. The way to know the difference is
     352                    // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB
     353                    // triple.
     354                    $ng = count($this->grad_fromcolor);
     355                    if( $ng === 3 ) {
     356                        if( is_numeric($this->grad_fromcolor[0]) && $this->grad_fromcolor[0] > 0 && $this->grad_fromcolor[0] < 256 ) {
     357                            // RGB Triple
     358                            $fromcolor = $this->grad_fromcolor;
     359                            $tocolor = $this->grad_tocolor;
     360                            $style = $this->grad_style;
     361                        }
     362                    }
     363                    else {
     364                        $fromcolor = $this->grad_fromcolor[$i % $ng][0];
     365                        $tocolor = $this->grad_fromcolor[$i % $ng][1];
     366                        $style = $this->grad_fromcolor[$i % $ng][2];
     367                    }
     368                    $grad->FilledRectangle($pts[2],$pts[3],
     369                                           $pts[6],$pts[7],
     370                                           $fromcolor,$tocolor,$style);
     371                }
     372                else {
     373                    $grad->FilledRectangle($pts[2],$pts[3],
     374                                           $pts[6],$pts[7],
     375                                           $this->grad_fromcolor,$this->grad_tocolor,$this->grad_style);
     376                }
     377            }
     378            elseif( !empty($this->fill_color) ) {
     379                if(is_array($this->fill_color)) {
     380                    $img->PushColor($this->fill_color[$i % count($this->fill_color)]);
     381                } else {
     382                    $img->PushColor($this->fill_color);
     383                }
     384                $img->FilledPolygon($pts);
     385                $img->PopColor();
     386            }
     387 
     388                       
     389            // Remember value of this bar
     390            $val=$this->coords[0][$i];
     391
     392            if( !empty($val) && !is_numeric($val) ) {
     393                JpGraphError::RaiseL(2004,$i,$val);
     394                //'All values for a barplot must be numeric. You have specified value['.$i.'] == \''.$val.'\'');
     395            }
     396
     397            // Determine the shadow
     398            if( $this->bar_shadow && $val != 0) {
     399
     400                $ssh = $this->bar_shadow_hsize;
     401                $ssv = $this->bar_shadow_vsize;
     402                // Create points to create a "upper-right" shadow
     403                if( $val > 0 ) {
     404                    $sp[0]=$pts[6];             $sp[1]=$pts[7];
     405                    $sp[2]=$pts[4];             $sp[3]=$pts[5];
     406                    $sp[4]=$pts[2];             $sp[5]=$pts[3];
     407                    $sp[6]=$pts[2]+$ssh;        $sp[7]=$pts[3]-$ssv;
     408                    $sp[8]=$pts[4]+$ssh;        $sp[9]=$pts[5]-$ssv;
     409                    $sp[10]=$pts[6]+$ssh;       $sp[11]=$pts[7]-$ssv;
     410                }
     411                elseif( $val < 0 ) {
     412                    $sp[0]=$pts[4];             $sp[1]=$pts[5];
     413                    $sp[2]=$pts[6];             $sp[3]=$pts[7];
     414                    $sp[4]=$pts[0];             $sp[5]=$pts[1];
     415                    $sp[6]=$pts[0]+$ssh;        $sp[7]=$pts[1]-$ssv;
     416                    $sp[8]=$pts[6]+$ssh;        $sp[9]=$pts[7]-$ssv;
     417                    $sp[10]=$pts[4]+$ssh;       $sp[11]=$pts[5]-$ssv;
     418                }
     419                if( is_array($this->bar_shadow_color) ) {
     420                    $numcolors = count($this->bar_shadow_color);
     421                    if( $numcolors == 0 ) {
     422                        JpGraphError::RaiseL(2005);//('You have specified an empty array for shadow colors in the bar plot.');
     423                    }
     424                    $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
     425                }
     426                else {
     427                    $img->PushColor($this->bar_shadow_color);
     428                }
     429                $img->FilledPolygon($sp);
     430                $img->PopColor();
     431            }
     432                       
     433            // Stroke the pattern
     434            if( is_array($this->iPattern) ) {
     435                $f = new RectPatternFactory();
     436                if( is_array($this->iPatternColor) ) {
     437                    $pcolor = $this->iPatternColor[$i % $np];
     438                }
     439                else
     440                    $pcolor = $this->iPatternColor;
     441                $prect = $f->Create($this->iPattern[$i % $np],$pcolor,1);
     442                $prect->SetDensity($this->iPatternDensity[$i % $np]);
     443
     444                if( $val < 0 ) {
     445                    $rx = $pts[0];
     446                    $ry = $pts[1];
     447                }
     448                else {
     449                    $rx = $pts[2];
     450                    $ry = $pts[3];
     451                }
     452                $width = abs($pts[4]-$pts[0])+1;
     453                $height = abs($pts[1]-$pts[3])+1;
     454                $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
     455                $prect->Stroke($img);
     456            }
     457            else {
     458                if( $this->iPattern > -1 ) {
     459                    $f = new RectPatternFactory();
     460                    $prect = $f->Create($this->iPattern,$this->iPatternColor,1);
     461                    $prect->SetDensity($this->iPatternDensity);
     462                    if( $val < 0 ) {
     463                        $rx = $pts[0];
     464                        $ry = $pts[1];
     465                    }
     466                    else {
     467                        $rx = $pts[2];
     468                        $ry = $pts[3];
     469                    }
     470                    $width = abs($pts[4]-$pts[0])+1;
     471                    $height = abs($pts[1]-$pts[3])+1;
     472                    $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
     473                    $prect->Stroke($img);
     474                }
     475            }
     476            // Stroke the outline of the bar
     477            if( is_array($this->color) )
     478                $img->SetColor($this->color[$i % count($this->color)]);
     479            else
     480                $img->SetColor($this->color);
     481
     482            $pts[] = $pts[0];
     483            $pts[] = $pts[1];
     484
     485            if( $this->weight > 0 ) {
     486                $img->SetLineWeight($this->weight);
     487                $img->Polygon($pts);
     488            }
     489                       
     490            // Determine how to best position the values of the individual bars
     491            $x=$pts[2]+($pts[4]-$pts[2])/2;
     492            $this->value->SetMargin(5);
     493
     494            if( $this->valuepos=='top' ) {
     495                $y=$pts[3];
     496                if( $img->a === 90 ) {
     497                    if( $val < 0 )
     498                        $this->value->SetAlign('right','center');                       
     499                    else
     500                        $this->value->SetAlign('left','center');
     501                       
     502                }
     503                else {
     504                    if( $val < 0 ) {
     505                        $this->value->SetMargin(-5);
     506                        $y=$pts[1];
     507                        $this->value->SetAlign('center','bottom');
     508                    }
     509                    else {
     510                        $this->value->SetAlign('center','bottom');                     
     511                    }
     512
     513                }
     514                $this->value->Stroke($img,$val,$x,$y);
     515            }
     516            elseif( $this->valuepos=='max' ) {
     517                $y=$pts[3];
     518                if( $img->a === 90 ) {
     519                    if( $val < 0 )
     520                        $this->value->SetAlign('left','center');
     521                    else
     522                        $this->value->SetAlign('right','center');                   
     523                }
     524                else {
     525                    if( $val < 0 ) {
     526                        $this->value->SetAlign('center','bottom');
     527                    }
     528                    else {
     529                        $this->value->SetAlign('center','top');
     530                    }
     531                }
     532                $this->value->SetMargin(-5);
     533                $this->value->Stroke($img,$val,$x,$y);
     534            }
     535            elseif( $this->valuepos=='center' ) {
     536                $y = ($pts[3] + $pts[1])/2;
     537                $this->value->SetAlign('center','center');
     538                $this->value->SetMargin(0);
     539                $this->value->Stroke($img,$val,$x,$y);
     540            }
     541            elseif( $this->valuepos=='bottom' || $this->valuepos=='min' ) {
     542                $y=$pts[1];
     543                if( $img->a === 90 ) {
     544                    if( $val < 0 )
     545                        $this->value->SetAlign('right','center');
     546                    else
     547                        $this->value->SetAlign('left','center');                                   
     548                }
     549                $this->value->SetMargin(3);
     550                $this->value->Stroke($img,$val,$x,$y);
     551            }
     552            else {
     553                JpGraphError::RaiseL(2006,$this->valuepos);
     554                //'Unknown position for values on bars :'.$this->valuepos);
     555            }
     556            // Create the client side image map
     557            $rpts = $img->ArrRotate($pts);             
     558            $csimcoord=round($rpts[0]).", ".round($rpts[1]);
     559            for( $j=1; $j < 4; ++$j){
     560                $csimcoord .= ", ".round($rpts[2*$j]).", ".round($rpts[2*$j+1]);
     561            }               
     562            if( !empty($this->csimtargets[$i]) ) {
     563                $this->csimareas .= '<area shape="poly" coords="'.$csimcoord.'" ';         
     564                $this->csimareas .= " href=\"".htmlentities($this->csimtargets[$i])."\"";
     565
     566                if( !empty($this->csimwintargets[$i]) ) {
     567                    $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
     568                }
     569
     570                $sval='';
     571                if( !empty($this->csimalts[$i]) ) {
     572                    $sval=sprintf($this->csimalts[$i],$this->coords[0][$i]);
     573                    $this->csimareas .= " title=\"$sval\" alt=\"$sval\" ";
     574                }
     575                $this->csimareas .= " />\n";
     576            }
     577        }
     578        return true;
    672579    }
    673580} // Class
     
    678585//===================================================
    679586class GroupBarPlot extends BarPlot {
    680     public $plots;
    681     private $nbrplots=0;
    682     //---------------
    683     // CONSTRUCTOR
    684     function __construct($plots) {
    685         $this->width=0.7;
    686         $this->plots = $plots;
    687         $this->nbrplots = count($plots);
    688         if( $this->nbrplots < 1 ) {
    689             JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.');
    690         }
    691         for($i=0; $i < $this->nbrplots; ++$i ) {
    692             if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
    693                 JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty.");
    694             }
    695         }
    696         $this->numpoints = $plots[0]->numpoints;
    697         $this->width=0.7;
    698     }
    699 
    700     //---------------
    701     // PUBLIC METHODS
     587    private $plots, $nbrplots=0;
     588//---------------
     589// CONSTRUCTOR
     590    function GroupBarPlot($plots) {
     591        $this->width=0.7;
     592        $this->plots = $plots;
     593        $this->nbrplots = count($plots);
     594        if( $this->nbrplots < 1 ) {
     595            JpGraphError::RaiseL(2007);//('Cannot create GroupBarPlot from empty plot array.');
     596        }
     597        for($i=0; $i < $this->nbrplots; ++$i ) {
     598            if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
     599                JpGraphError::RaiseL(2008,$i);//("Group bar plot element nbr $i is undefined or empty.");
     600            }
     601        }
     602        $this->numpoints = $plots[0]->numpoints;
     603        $this->width=0.7;
     604    }
     605
     606//---------------
     607// PUBLIC METHODS       
    702608    function Legend($graph) {
    703         $n = count($this->plots);
    704         for($i=0; $i < $n; ++$i) {
    705             $c = get_class($this->plots[$i]);
    706             if( !($this->plots[$i] instanceof BarPlot) ) {
    707                 JpGraphError::RaiseL(2009,$c);
    708                 //('One of the objects submitted to GroupBar is not a BarPlot. Make sure that you create the Group Bar plot from an array of BarPlot or AccBarPlot objects. (Class = '.$c.')');
    709             }
    710             $this->plots[$i]->DoLegend($graph);
    711         }
    712     }
    713 
     609        $n = count($this->plots);
     610        for($i=0; $i < $n; ++$i) {
     611            $c = get_class($this->plots[$i]);
     612            if( !($this->plots[$i] instanceof BarPlot) ) {
     613                JpGraphError::RaiseL(2009,$c);
     614//('One of the objects submitted to GroupBar is not a BarPlot. Make sure that you create the Group Bar plot from an array of BarPlot or AccBarPlot objects. (Class = '.$c.')');
     615            }
     616            $this->plots[$i]->DoLegend($graph);
     617        }
     618    }
     619       
    714620    function Min() {
    715         list($xmin,$ymin) = $this->plots[0]->Min();
    716         $n = count($this->plots);
    717         for($i=0; $i < $n; ++$i) {
    718             list($xm,$ym) = $this->plots[$i]->Min();
    719             $xmin = max($xmin,$xm);
    720             $ymin = min($ymin,$ym);
    721         }
    722         return array($xmin,$ymin);
    723     }
    724 
     621        list($xmin,$ymin) = $this->plots[0]->Min();
     622        $n = count($this->plots);
     623        for($i=0; $i < $n; ++$i) {
     624            list($xm,$ym) = $this->plots[$i]->Min();
     625            $xmin = max($xmin,$xm);
     626            $ymin = min($ymin,$ym);
     627        }
     628        return array($xmin,$ymin);             
     629    }
     630       
    725631    function Max() {
    726         list($xmax,$ymax) = $this->plots[0]->Max();
    727         $n = count($this->plots);
    728         for($i=0; $i < $n; ++$i) {
    729             list($xm,$ym) = $this->plots[$i]->Max();
    730             $xmax = max($xmax,$xm);
    731             $ymax = max($ymax,$ym);
    732         }
    733         return array($xmax,$ymax);
    734     }
    735 
     632        list($xmax,$ymax) = $this->plots[0]->Max();
     633        $n = count($this->plots);
     634        for($i=0; $i < $n; ++$i) {
     635            list($xm,$ym) = $this->plots[$i]->Max();
     636            $xmax = max($xmax,$xm);
     637            $ymax = max($ymax,$ym);
     638        }
     639        return array($xmax,$ymax);
     640    }
     641       
    736642    function GetCSIMareas() {
    737         $n = count($this->plots);
    738         $csimareas='';
    739         for($i=0; $i < $n; ++$i) {
    740             $csimareas .= $this->plots[$i]->csimareas;
    741         }
    742         return $csimareas;
    743     }
    744 
     643        $n = count($this->plots);
     644        $csimareas='';
     645        for($i=0; $i < $n; ++$i) {
     646            $csimareas .= $this->plots[$i]->csimareas;
     647        }
     648        return $csimareas;
     649    }
     650       
    745651    // Stroke all the bars next to each other
    746     function Stroke($img,$xscale,$yscale) {
    747         $tmp=$xscale->off;
    748         $n = count($this->plots);
    749         $subwidth = $this->width/$this->nbrplots ;
    750 
    751         for( $i=0; $i < $n; ++$i ) {
    752             $this->plots[$i]->ymin=$this->ybase;
    753             $this->plots[$i]->SetWidth($subwidth);
    754 
    755             // If the client have used SetTextTickInterval() then
    756             // major_step will be > 1 and the positioning will fail.
    757             // If we assume it is always one the positioning will work
    758             // fine with a text scale but this will not work with
    759             // arbitrary linear scale
    760             $xscale->off = $tmp+$i*round($xscale->scale_factor* $subwidth);
    761             $this->plots[$i]->Stroke($img,$xscale,$yscale);
    762         }
    763         $xscale->off=$tmp;
     652    function Stroke($img,$xscale,$yscale) { 
     653        $tmp=$xscale->off;
     654        $n = count($this->plots);
     655        $subwidth = $this->width/$this->nbrplots ;
     656
     657        for( $i=0; $i < $n; ++$i ) {
     658            $this->plots[$i]->ymin=$this->ybase;
     659            $this->plots[$i]->SetWidth($subwidth);
     660           
     661            // If the client have used SetTextTickInterval() then
     662            // major_step will be > 1 and the positioning will fail.
     663            // If we assume it is always one the positioning will work
     664            // fine with a text scale but this will not work with
     665            // arbitrary linear scale
     666            $xscale->off = $tmp+$i*round($xscale->scale_factor* $subwidth);
     667            $this->plots[$i]->Stroke($img,$xscale,$yscale);
     668        }
     669        $xscale->off=$tmp;
    764670    }
    765671} // Class
     
    770676//===================================================
    771677class AccBarPlot extends BarPlot {
    772     public $plots=null;
    773     private $nbrplots=0;
    774     //---------------
    775     // CONSTRUCTOR
    776     function __construct($plots) {
    777         $this->plots = $plots;
    778         $this->nbrplots = count($plots);
    779         if( $this->nbrplots < 1 ) {
    780             JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.');
    781         }
    782         for($i=0; $i < $this->nbrplots; ++$i ) {
    783             if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
    784                 JpGraphError::RaiseL(2011,$i);//("Acc bar plot element nbr $i is undefined or empty.");
    785             }
    786         }
    787 
    788         // We can only allow individual plost which do not have specified X-positions
    789         for($i=0; $i < $this->nbrplots; ++$i ) {
    790             if( !empty($this->plots[$i]->coords[1]) ) {
    791                 JpGraphError::RaiseL(2015);
    792                 //'Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-positions.');
    793             }
    794         }
    795 
    796         // Use 0 weight by default which means that the individual bar
    797         // weights will be used per part n the accumulated bar
    798         $this->SetWeight(0);
    799 
    800         $this->numpoints = $plots[0]->numpoints;
    801         $this->value = new DisplayValue();
    802     }
    803 
    804     //---------------
    805     // PUBLIC METHODS
     678    private $plots=null,$nbrplots=0;
     679//---------------
     680// CONSTRUCTOR
     681    function AccBarPlot($plots) {
     682        $this->plots = $plots;
     683        $this->nbrplots = count($plots);
     684        if( $this->nbrplots < 1 ) {
     685            JpGraphError::RaiseL(2010);//('Cannot create AccBarPlot from empty plot array.');
     686        }
     687        for($i=0; $i < $this->nbrplots; ++$i ) {
     688            if( empty($this->plots[$i]) || !isset($this->plots[$i]) ) {
     689                JpGraphError::RaiseL(2011,$i);//("Acc bar plot element nbr $i is undefined or empty.");
     690            }
     691        }
     692
     693// We can only allow individual plost which do not have specified X-positions
     694        for($i=0; $i < $this->nbrplots; ++$i ) {
     695            if( !empty($this->plots[$i]->coords[1]) ) {
     696                JpGraphError::RaiseL(2015);
     697                //'Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-positions.');
     698            }
     699        }
     700       
     701        $this->numpoints = $plots[0]->numpoints;               
     702        $this->value = new DisplayValue();
     703    }
     704
     705//---------------
     706// PUBLIC METHODS       
    806707    function Legend($graph) {
    807         $n = count($this->plots);
    808         for( $i=$n-1; $i >= 0; --$i ) {
    809             $c = get_class($this->plots[$i]);
    810             if( !($this->plots[$i] instanceof BarPlot) ) {
    811                 JpGraphError::RaiseL(2012,$c);
    812                 //('One of the objects submitted to AccBar is not a BarPlot. Make sure that you create the AccBar plot from an array of BarPlot objects.(Class='.$c.')');
    813             }
    814             $this->plots[$i]->DoLegend($graph);
    815         }
     708        $n = count($this->plots);
     709        for( $i=$n-1; $i >= 0; --$i ) {
     710            $c = get_class($this->plots[$i]);
     711            if( !($this->plots[$i] instanceof BarPlot) ) {
     712                JpGraphError::RaiseL(2012,$c);
     713//('One of the objects submitted to AccBar is not a BarPlot. Make sure that you create the AccBar plot from an array of BarPlot objects.(Class='.$c.')');
     714            }       
     715            $this->plots[$i]->DoLegend($graph);
     716        }
    816717    }
    817718
    818719    function Max() {
    819         list($xmax) = $this->plots[0]->Max();
    820         $nmax=0;
    821         for($i=0; $i < count($this->plots); ++$i) {
    822             $n = count($this->plots[$i]->coords[0]);
    823             $nmax = max($nmax,$n);
    824             list($x) = $this->plots[$i]->Max();
    825             $xmax = max($xmax,$x);
    826         }
    827         for( $i = 0; $i < $nmax; $i++ ) {
    828             // Get y-value for bar $i by adding the
    829             // individual bars from all the plots added.
    830             // It would be wrong to just add the
    831             // individual plots max y-value since that
    832             // would in most cases give to large y-value.
    833             $y=0;
    834             if( !isset($this->plots[0]->coords[0][$i]) ) {
    835                 JpGraphError::RaiseL(2014);
    836             }
    837             if( $this->plots[0]->coords[0][$i] > 0 )
    838             $y=$this->plots[0]->coords[0][$i];
    839             for( $j = 1; $j < $this->nbrplots; $j++ ) {
    840                 if( !isset($this->plots[$j]->coords[0][$i]) ) {
    841                     JpGraphError::RaiseL(2014);
    842                 }
    843                 if( $this->plots[$j]->coords[0][$i] > 0 )
    844                 $y += $this->plots[$j]->coords[0][$i];
    845             }
    846             $ymax[$i] = $y;
    847         }
    848         $ymax = max($ymax);
    849 
    850         // Bar always start at baseline
    851         if( $ymax <= $this->ybase )
    852         $ymax = $this->ybase;
    853         return array($xmax,$ymax);
     720        list($xmax) = $this->plots[0]->Max();
     721        $nmax=0;
     722        for($i=0; $i < count($this->plots); ++$i) {
     723            $n = count($this->plots[$i]->coords[0]);
     724            $nmax = max($nmax,$n);
     725            list($x) = $this->plots[$i]->Max();
     726            $xmax = max($xmax,$x);
     727        }
     728        for( $i = 0; $i < $nmax; $i++ ) {
     729            // Get y-value for bar $i by adding the
     730            // individual bars from all the plots added.
     731            // It would be wrong to just add the
     732            // individual plots max y-value since that
     733            // would in most cases give to large y-value.
     734            $y=0;
     735            if( !isset($this->plots[0]->coords[0][$i]) ) {
     736                JpGraphError::RaiseL(2014);
     737            }
     738            if( $this->plots[0]->coords[0][$i] > 0 )
     739                $y=$this->plots[0]->coords[0][$i];
     740            for( $j = 1; $j < $this->nbrplots; $j++ ) {
     741                if( !isset($this->plots[$j]->coords[0][$i]) ) {
     742                    JpGraphError::RaiseL(2014);
     743                }
     744                if( $this->plots[$j]->coords[0][$i] > 0 )
     745                    $y += $this->plots[$j]->coords[0][$i];
     746            }
     747            $ymax[$i] = $y;
     748        }
     749        $ymax = max($ymax);
     750
     751        // Bar always start at baseline
     752        if( $ymax <= $this->ybase )
     753            $ymax = $this->ybase;
     754        return array($xmax,$ymax);
    854755    }
    855756
    856757    function Min() {
    857         $nmax=0;
    858         list($xmin,$ysetmin) = $this->plots[0]->Min();
    859         for($i=0; $i < count($this->plots); ++$i) {
    860             $n = count($this->plots[$i]->coords[0]);
    861             $nmax = max($nmax,$n);
    862             list($x,$y) = $this->plots[$i]->Min();
    863             $xmin = Min($xmin,$x);
    864             $ysetmin = Min($y,$ysetmin);
    865         }
    866         for( $i = 0; $i < $nmax; $i++ ) {
    867             // Get y-value for bar $i by adding the
    868             // individual bars from all the plots added.
    869             // It would be wrong to just add the
    870             // individual plots max y-value since that
    871             // would in most cases give to large y-value.
    872             $y=0;
    873             if( $this->plots[0]->coords[0][$i] < 0 )
    874             $y=$this->plots[0]->coords[0][$i];
    875             for( $j = 1; $j < $this->nbrplots; $j++ ) {
    876                 if( $this->plots[$j]->coords[0][$i] < 0 )
    877                 $y += $this->plots[ $j ]->coords[0][$i];
    878             }
    879             $ymin[$i] = $y;
    880         }
    881         $ymin = Min($ysetmin,Min($ymin));
    882         // Bar always start at baseline
    883         if( $ymin >= $this->ybase )
    884         $ymin = $this->ybase;
    885         return array($xmin,$ymin);
     758        $nmax=0;
     759        list($xmin,$ysetmin) = $this->plots[0]->Min();
     760        for($i=0; $i < count($this->plots); ++$i) {
     761            $n = count($this->plots[$i]->coords[0]);
     762            $nmax = max($nmax,$n);
     763            list($x,$y) = $this->plots[$i]->Min();
     764            $xmin = Min($xmin,$x);
     765            $ysetmin = Min($y,$ysetmin);
     766        }
     767        for( $i = 0; $i < $nmax; $i++ ) {
     768            // Get y-value for bar $i by adding the
     769            // individual bars from all the plots added.
     770            // It would be wrong to just add the
     771            // individual plots max y-value since that
     772            // would in most cases give to large y-value.
     773            $y=0;
     774            if( $this->plots[0]->coords[0][$i] < 0 )
     775                $y=$this->plots[0]->coords[0][$i];
     776            for( $j = 1; $j < $this->nbrplots; $j++ ) {
     777                if( $this->plots[$j]->coords[0][$i] < 0 )
     778                    $y += $this->plots[ $j ]->coords[0][$i];
     779            }
     780            $ymin[$i] = $y;
     781        }
     782        $ymin = Min($ysetmin,Min($ymin));
     783        // Bar always start at baseline
     784        if( $ymin >= $this->ybase )
     785            $ymin = $this->ybase;
     786        return array($xmin,$ymin);
    886787    }
    887788
    888789    // Stroke acc bar plot
    889790    function Stroke($img,$xscale,$yscale) {
    890         $pattern=NULL;
    891         $img->SetLineWeight($this->weight);
    892         $grad=null;
    893         for($i=0; $i < $this->numpoints-1; $i++) {
    894             $accy = 0;
    895             $accy_neg = 0;
    896             for($j=0; $j < $this->nbrplots; ++$j ) {
    897                 $img->SetColor($this->plots[$j]->color);
    898 
    899                 if ( $this->plots[$j]->coords[0][$i] >= 0) {
    900                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
    901                     $accyt=$yscale->Translate($accy);
    902                     $accy+=$this->plots[$j]->coords[0][$i];
    903                 }
    904                 else {
    905                     //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) {
    906                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
    907                     $accyt=$yscale->Translate($accy_neg);
    908                     $accy_neg+=$this->plots[$j]->coords[0][$i];
    909                 }
    910 
    911                 $xt=$xscale->Translate($i);
    912 
    913                 if( $this->abswidth > -1 ) {
    914                     $abswidth=$this->abswidth;
    915                 }
    916                 else {
    917                     $abswidth=round($this->width*$xscale->scale_factor,0);
    918                 }
    919 
    920                 $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt);
    921 
    922                 if( $this->bar_shadow ) {
    923                     $ssh = $this->bar_shadow_hsize;
    924                     $ssv = $this->bar_shadow_vsize;
    925 
    926                     // We must also differ if we are a positive or negative bar.
    927                     if( $j === 0 ) {
    928                         // This gets extra complicated since we have to
    929                         // see all plots to see if we are negative. It could
    930                         // for example be that all plots are 0 until the very
    931                         // last one. We therefore need to save the initial setup
    932                         // for both the negative and positive case
    933 
    934                         // In case the final bar is positive
    935                         $sp[0]=$pts[6]+1; $sp[1]=$pts[7];
    936                         $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv;
    937 
    938                         // In case the final bar is negative
    939                         $nsp[0]=$pts[0]; $nsp[1]=$pts[1];
    940                         $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv;
    941                         $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv;
    942                         $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7];
    943                     }
    944 
    945                     if( $j === $this->nbrplots-1 ) {
    946                         // If this is the last plot of the bar and
    947                         // the total value is larger than 0 then we
    948                         // add the shadow.
    949                         if( is_array($this->bar_shadow_color) ) {
    950                             $numcolors = count($this->bar_shadow_color);
    951                             if( $numcolors == 0 ) {
    952                                 JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.');
    953                             }
    954                             $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
    955                         }
    956                         else {
    957                             $img->PushColor($this->bar_shadow_color);
    958                         }
    959 
    960                         if( $accy > 0 ) {
    961                             $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv;
    962                             $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
    963                             $sp[8]=$pts[2]; $sp[9]=$pts[3]-1;
    964                             $sp[10]=$pts[4]+1; $sp[11]=$pts[5];
    965                             $img->FilledPolygon($sp,4);
    966                         }
    967                         elseif( $accy_neg < 0 ) {
    968                             $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv;
    969                             $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5];
    970                             $img->FilledPolygon($nsp,4);
    971                         }
    972                         $img->PopColor();
    973                     }
    974                 }
    975 
    976 
    977                 // If value is NULL or 0, then don't draw a bar at all
    978                 if ($this->plots[$j]->coords[0][$i] == 0 ) continue;
    979 
    980                 if( $this->plots[$j]->grad ) {
    981                     if( $grad === null ) {
    982                         $grad = new Gradient($img);
    983                     }
    984                     if( is_array($this->plots[$j]->grad_fromcolor) ) {
    985                         // The first argument (grad_fromcolor) can be either an array or a single color. If it is an array
    986                         // then we have two choices. It can either a) be a single color specified as an RGB triple or it can be
    987                         // an array to specify both (from, to style) for each individual bar. The way to know the difference is
    988                         // to investgate the first element. If this element is an integer [0,255] then we assume it is an RGB
    989                         // triple.
    990                         $ng = count($this->plots[$j]->grad_fromcolor);
    991                         if( $ng === 3 ) {
    992                             if( is_numeric($this->plots[$j]->grad_fromcolor[0]) && $this->plots[$j]->grad_fromcolor[0] > 0 &&
    993                                  $this->plots[$j]->grad_fromcolor[0] < 256 ) {
    994                                 // RGB Triple
    995                                 $fromcolor = $this->plots[$j]->grad_fromcolor;
    996                                 $tocolor = $this->plots[$j]->grad_tocolor;
    997                                 $style = $this->plots[$j]->grad_style;
    998                             }
    999                             else {
    1000                                 $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0];
    1001                                 $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1];
    1002                                 $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2];
    1003                             }
    1004                         }
    1005                         else {
    1006                             $fromcolor = $this->plots[$j]->grad_fromcolor[$i % $ng][0];
    1007                             $tocolor = $this->plots[$j]->grad_fromcolor[$i % $ng][1];
    1008                             $style = $this->plots[$j]->grad_fromcolor[$i % $ng][2];
    1009                         }
    1010                         $grad->FilledRectangle($pts[2],$pts[3],
    1011                                                $pts[6],$pts[7],
    1012                                                $fromcolor,$tocolor,$style);
    1013                     }
    1014                     else {
    1015                         $grad->FilledRectangle($pts[2],$pts[3],
    1016                                                $pts[6],$pts[7],
    1017                                                $this->plots[$j]->grad_fromcolor,
    1018                                                $this->plots[$j]->grad_tocolor,
    1019                                                $this->plots[$j]->grad_style);
    1020                     }
    1021                 } else {
    1022                     if (is_array($this->plots[$j]->fill_color) ) {
    1023                         $numcolors = count($this->plots[$j]->fill_color);
    1024                         $fillcolor = $this->plots[$j]->fill_color[$i % $numcolors];
    1025                         // If the bar is specified to be non filled then the fill color is false
    1026                         if( $fillcolor !== false ) {
    1027                             $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]);
    1028                         }
    1029                     }
    1030                     else {
    1031                         $fillcolor = $this->plots[$j]->fill_color;
    1032                         if( $fillcolor !== false ) {
    1033                             $img->SetColor($this->plots[$j]->fill_color);
    1034                         }
    1035                     }
    1036                     if( $fillcolor !== false ) {
    1037                         $img->FilledPolygon($pts);
    1038                     }
    1039                 }
    1040 
    1041                 $img->SetColor($this->plots[$j]->color);
    1042 
    1043                 // Stroke the pattern
    1044                 if( $this->plots[$j]->iPattern > -1 ) {
    1045                     if( $pattern===NULL ) {
    1046                         $pattern = new RectPatternFactory();
    1047                     }
    1048 
    1049                     $prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1);
    1050                     $prect->SetDensity($this->plots[$j]->iPatternDensity);
    1051                     if( $this->plots[$j]->coords[0][$i] < 0 ) {
    1052                         $rx = $pts[0];
    1053                         $ry = $pts[1];
    1054                     }
    1055                     else {
    1056                         $rx = $pts[2];
    1057                         $ry = $pts[3];
    1058                     }
    1059                     $width = abs($pts[4]-$pts[0])+1;
    1060                     $height = abs($pts[1]-$pts[3])+1;
    1061                     $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
    1062                     $prect->Stroke($img);
    1063                 }
    1064 
    1065 
    1066                 // CSIM array
    1067 
    1068                 if( $i < count($this->plots[$j]->csimtargets) ) {
    1069                     // Create the client side image map
    1070                     $rpts = $img->ArrRotate($pts);
    1071                     $csimcoord=round($rpts[0]).", ".round($rpts[1]);
    1072                     for( $k=1; $k < 4; ++$k){
    1073                         $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]);
    1074                     }
    1075                     if( ! empty($this->plots[$j]->csimtargets[$i]) ) {
    1076                         $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" ';
    1077                         $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\" ";
    1078 
    1079                         if( ! empty($this->plots[$j]->csimwintargets[$i]) ) {
    1080                             $this->csimareas.= " target=\"".$this->plots[$j]->csimwintargets[$i]."\" ";
    1081                         }
    1082 
    1083                         $sval='';
    1084                         if( !empty($this->plots[$j]->csimalts[$i]) ) {
    1085                             $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]);
    1086                             $this->csimareas .= " title=\"$sval\" ";
    1087                         }
    1088                         $this->csimareas .= " alt=\"$sval\" />\n";
    1089                     }
    1090                 }
    1091 
    1092                 $pts[] = $pts[0];
    1093                 $pts[] = $pts[1];
    1094                 $img->SetLineWeight($this->plots[$j]->weight);
    1095                 $img->Polygon($pts);
    1096                 $img->SetLineWeight(1);
    1097             }
    1098 
    1099             // Daw potential bar around the entire accbar bar
    1100             if( $this->weight > 0 ) {
    1101                 $y=$yscale->Translate(0);
    1102                 $img->SetColor($this->color);
    1103                 $img->SetLineWeight($this->weight);
    1104                 $img->Rectangle($pts[0],$y,$pts[6],$pts[5]);
    1105             }
    1106 
    1107             // Draw labels for each acc.bar
    1108 
    1109             $x=$pts[2]+($pts[4]-$pts[2])/2;
    1110             if($this->bar_shadow) $x += $ssh;
    1111 
    1112             // First stroke the accumulated value for the entire bar
    1113             // This value is always placed at the top/bottom of the bars
    1114             if( $accy + $accy_neg < 0 ) {
    1115                 $y=$yscale->Translate($accy_neg);
    1116             }
    1117             else {
    1118                 $y=$yscale->Translate($accy);
    1119             }
    1120             $this->value->Stroke($img,$accy + $accy_neg,$x,$y);
    1121 
    1122             $accy = 0;
    1123             $accy_neg = 0;
    1124             for($j=0; $j < $this->nbrplots; ++$j ) {
    1125 
    1126                 // We don't print 0 values in an accumulated bar plot
    1127                 if( $this->plots[$j]->coords[0][$i] == 0 ) continue;
    1128 
    1129                 if ($this->plots[$j]->coords[0][$i] > 0) {
    1130                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
    1131                     $accyt=$yscale->Translate($accy);
    1132                     if(  $this->plots[$j]->valuepos=='center' ) {
    1133                         $y = $accyt-($accyt-$yt)/2;
    1134                     }
    1135                     elseif( $this->plots[$j]->valuepos=='bottom' ) {
    1136                         $y = $accyt;
    1137                     }
    1138                     else { // top or max
    1139                         $y = $accyt-($accyt-$yt);
    1140                     }
    1141                     $accy+=$this->plots[$j]->coords[0][$i];
    1142                     if(  $this->plots[$j]->valuepos=='center' ) {
    1143                         $this->plots[$j]->value->SetAlign("center","center");
    1144                         $this->plots[$j]->value->SetMargin(0);
    1145                     }
    1146                     elseif( $this->plots[$j]->valuepos=='bottom' ) {
    1147                         $this->plots[$j]->value->SetAlign('center','bottom');
    1148                         $this->plots[$j]->value->SetMargin(2);
    1149                     }
    1150                     else {
    1151                         $this->plots[$j]->value->SetAlign('center','top');
    1152                         $this->plots[$j]->value->SetMargin(1);
    1153                     }
    1154                 } else {
    1155                     $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
    1156                     $accyt=$yscale->Translate($accy_neg);
    1157                     $accy_neg+=$this->plots[$j]->coords[0][$i];
    1158                     if(  $this->plots[$j]->valuepos=='center' ) {
    1159                         $y = $accyt-($accyt-$yt)/2;
    1160                     }
    1161                     elseif( $this->plots[$j]->valuepos=='bottom' ) {
    1162                         $y = $accyt;
    1163                     }
    1164                     else {
    1165                         $y = $accyt-($accyt-$yt);
    1166                     }
    1167                     if(  $this->plots[$j]->valuepos=='center' ) {
    1168                         $this->plots[$j]->value->SetAlign("center","center");
    1169                         $this->plots[$j]->value->SetMargin(0);
    1170                     }
    1171                     elseif( $this->plots[$j]->valuepos=='bottom' ) {
    1172                         $this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top');
    1173                         $this->plots[$j]->value->SetMargin(-2);
    1174                     }
    1175                     else {
    1176                         $this->plots[$j]->value->SetAlign('center','bottom');
    1177                         $this->plots[$j]->value->SetMargin(-1);
    1178                     }
    1179                 }
    1180                 $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],round($x),round($y));
    1181             }
    1182 
    1183         }
    1184         return true;
     791        $pattern=NULL;
     792        $img->SetLineWeight($this->weight);
     793        for($i=0; $i < $this->numpoints-1; $i++) {
     794            $accy = 0;
     795            $accy_neg = 0;
     796            for($j=0; $j < $this->nbrplots; ++$j ) {                           
     797                $img->SetColor($this->plots[$j]->color);
     798
     799                if ( $this->plots[$j]->coords[0][$i] >= 0) {
     800                    $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
     801                    $accyt=$yscale->Translate($accy);
     802                    $accy+=$this->plots[$j]->coords[0][$i];
     803                }
     804                else {
     805                    //if ( $this->plots[$j]->coords[0][$i] < 0 || $accy_neg < 0 ) {
     806                    $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
     807                    $accyt=$yscale->Translate($accy_neg);
     808                    $accy_neg+=$this->plots[$j]->coords[0][$i];
     809                }                               
     810                               
     811                $xt=$xscale->Translate($i);
     812
     813                if( $this->abswidth > -1 )
     814                    $abswidth=$this->abswidth;
     815                else
     816                    $abswidth=round($this->width*$xscale->scale_factor,0);
     817               
     818                $pts=array($xt,$accyt,$xt,$yt,$xt+$abswidth,$yt,$xt+$abswidth,$accyt);
     819
     820                if( $this->bar_shadow ) {
     821                    $ssh = $this->bar_shadow_hsize;
     822                    $ssv = $this->bar_shadow_vsize;
     823                   
     824                    // We must also differ if we are a positive or negative bar.
     825                    if( $j === 0 ) {
     826                        // This gets extra complicated since we have to
     827                        // see all plots to see if we are negative. It could
     828                        // for example be that all plots are 0 until the very
     829                        // last one. We therefore need to save the initial setup
     830                        // for both the negative and positive case
     831
     832                        // In case the final bar is positive
     833                        $sp[0]=$pts[6]+1; $sp[1]=$pts[7];
     834                        $sp[2]=$pts[6]+$ssh; $sp[3]=$pts[7]-$ssv;
     835
     836                        // In case the final bar is negative
     837                        $nsp[0]=$pts[0]; $nsp[1]=$pts[1];
     838                        $nsp[2]=$pts[0]+$ssh; $nsp[3]=$pts[1]-$ssv;
     839                        $nsp[4]=$pts[6]+$ssh; $nsp[5]=$pts[7]-$ssv;
     840                        $nsp[10]=$pts[6]+1; $nsp[11]=$pts[7];
     841                    }
     842
     843                    if( $j === $this->nbrplots-1 ) {
     844                        // If this is the last plot of the bar and
     845                        // the total value is larger than 0 then we
     846                        // add the shadow.
     847                        if( is_array($this->bar_shadow_color) ) {
     848                            $numcolors = count($this->bar_shadow_color);
     849                            if( $numcolors == 0 ) {
     850                                JpGraphError::RaiseL(2013);//('You have specified an empty array for shadow colors in the bar plot.');
     851                            }
     852                            $img->PushColor($this->bar_shadow_color[$i % $numcolors]);
     853                        }
     854                        else {
     855                            $img->PushColor($this->bar_shadow_color);
     856                        }
     857
     858                        if( $accy > 0 ) {
     859                            $sp[4]=$pts[4]+$ssh; $sp[5]=$pts[5]-$ssv;
     860                            $sp[6]=$pts[2]+$ssh; $sp[7]=$pts[3]-$ssv;
     861                            $sp[8]=$pts[2]; $sp[9]=$pts[3]-1;
     862                            $sp[10]=$pts[4]+1; $sp[11]=$pts[5];
     863                            $img->FilledPolygon($sp,4);
     864                        }
     865                        elseif( $accy_neg < 0 ) {
     866                            $nsp[6]=$pts[4]+$ssh; $nsp[7]=$pts[5]-$ssv;
     867                            $nsp[8]=$pts[4]+1; $nsp[9]=$pts[5];
     868                            $img->FilledPolygon($nsp,4);
     869                        }
     870                        $img->PopColor();
     871                    }
     872                }
     873
     874
     875                // If value is NULL or 0, then don't draw a bar at all
     876                if ($this->plots[$j]->coords[0][$i] == 0 ) continue;
     877
     878                if( $this->plots[$j]->grad ) {
     879                    $grad = new Gradient($img);
     880                    $grad->FilledRectangle(
     881                        $pts[2],$pts[3],
     882                        $pts[6],$pts[7],
     883                        $this->plots[$j]->grad_fromcolor,
     884                        $this->plots[$j]->grad_tocolor,
     885                        $this->plots[$j]->grad_style);                         
     886                } else {
     887                    if (is_array($this->plots[$j]->fill_color) ) {
     888                        $numcolors = count($this->plots[$j]->fill_color);
     889                        $fillcolor = $this->plots[$j]->fill_color[$i % $numcolors];
     890                        // If the bar is specified to be non filled then the fill color is false
     891                        if( $fillcolor !== false )
     892                            $img->SetColor($this->plots[$j]->fill_color[$i % $numcolors]);
     893                    }
     894                    else {
     895                        $fillcolor = $this->plots[$j]->fill_color;
     896                        if( $fillcolor !== false )
     897                            $img->SetColor($this->plots[$j]->fill_color);
     898                    }
     899                    if( $fillcolor !== false )
     900                        $img->FilledPolygon($pts);
     901                    $img->SetColor($this->plots[$j]->color);
     902                }                                 
     903
     904                // Stroke the pattern
     905                if( $this->plots[$j]->iPattern > -1 ) {
     906                    if( $pattern===NULL )
     907                        $pattern = new RectPatternFactory();
     908               
     909                    $prect = $pattern->Create($this->plots[$j]->iPattern,$this->plots[$j]->iPatternColor,1);
     910                    $prect->SetDensity($this->plots[$j]->iPatternDensity);
     911                    if( $this->plots[$j]->coords[0][$i] < 0 ) {
     912                        $rx = $pts[0];
     913                        $ry = $pts[1];
     914                    }
     915                    else {
     916                        $rx = $pts[2];
     917                        $ry = $pts[3];
     918                    }
     919                    $width = abs($pts[4]-$pts[0])+1;
     920                    $height = abs($pts[1]-$pts[3])+1;
     921                    $prect->SetPos(new Rectangle($rx,$ry,$width,$height));
     922                    $prect->Stroke($img);
     923                }
     924
     925
     926                // CSIM array
     927
     928                if( $i < count($this->plots[$j]->csimtargets) ) {
     929                    // Create the client side image map
     930                    $rpts = $img->ArrRotate($pts);             
     931                    $csimcoord=round($rpts[0]).", ".round($rpts[1]);
     932                    for( $k=1; $k < 4; ++$k){
     933                        $csimcoord .= ", ".round($rpts[2*$k]).", ".round($rpts[2*$k+1]);
     934                    }               
     935                    if( ! empty($this->plots[$j]->csimtargets[$i]) ) {
     936                        $this->csimareas.= '<area shape="poly" coords="'.$csimcoord.'" ';
     937                        $this->csimareas.= " href=\"".$this->plots[$j]->csimtargets[$i]."\" ";
     938
     939                        if( ! empty($this->plots[$j]->csimwintargets[$i]) ) {
     940                            $this->csimareas.= " target=\"".$this->plots[$j]->csimwintargets[$i]."\" ";
     941                        }
     942
     943                        $sval='';
     944                        if( !empty($this->plots[$j]->csimalts[$i]) ) {
     945                            $sval=sprintf($this->plots[$j]->csimalts[$i],$this->plots[$j]->coords[0][$i]);
     946                            $this->csimareas .= " title=\"$sval\" ";
     947                        }
     948                        $this->csimareas .= " alt=\"$sval\" />\n";                             
     949                    }
     950                }
     951
     952                $pts[] = $pts[0];
     953                $pts[] = $pts[1];
     954                $img->SetLineWeight($this->plots[$j]->line_weight);
     955                $img->Polygon($pts);
     956                $img->SetLineWeight(1);
     957            }
     958               
     959            // Draw labels for each acc.bar
     960       
     961            $x=$pts[2]+($pts[4]-$pts[2])/2;
     962            if($this->bar_shadow) $x += $ssh;
     963
     964            // First stroke the accumulated value for the entire bar
     965            // This value is always placed at the top/bottom of the bars
     966            if( $accy_neg < 0 ) {
     967                $y=$yscale->Translate($accy_neg);                       
     968                $this->value->Stroke($img,$accy_neg,$x,$y);
     969            }
     970            else {
     971                $y=$yscale->Translate($accy);                   
     972                $this->value->Stroke($img,$accy,$x,$y);
     973            }
     974
     975            $accy = 0;
     976            $accy_neg = 0;
     977            for($j=0; $j < $this->nbrplots; ++$j ) {   
     978
     979                // We don't print 0 values in an accumulated bar plot
     980                if( $this->plots[$j]->coords[0][$i] == 0 ) continue;
     981                       
     982                if ($this->plots[$j]->coords[0][$i] > 0) {
     983                    $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy);
     984                    $accyt=$yscale->Translate($accy);
     985                    if(  $this->plots[$j]->valuepos=='center' ) {
     986                        $y = $accyt-($accyt-$yt)/2;
     987                    }
     988                    elseif( $this->plots[$j]->valuepos=='bottom' ) {
     989                        $y = $accyt;
     990                    }
     991                    else { // top or max
     992                        $y = $accyt-($accyt-$yt);
     993                    }
     994                    $accy+=$this->plots[$j]->coords[0][$i];
     995                    if(  $this->plots[$j]->valuepos=='center' ) {
     996                        $this->plots[$j]->value->SetAlign("center","center");
     997                        $this->plots[$j]->value->SetMargin(0);
     998                    }
     999                    elseif( $this->plots[$j]->valuepos=='bottom' ) {
     1000                        $this->plots[$j]->value->SetAlign('center','bottom');
     1001                        $this->plots[$j]->value->SetMargin(2);
     1002                    }
     1003                    else {
     1004                        $this->plots[$j]->value->SetAlign('center','top');
     1005                        $this->plots[$j]->value->SetMargin(1);
     1006                    }
     1007                } else {
     1008                    $yt=$yscale->Translate($this->plots[$j]->coords[0][$i]+$accy_neg);
     1009                    $accyt=$yscale->Translate($accy_neg);
     1010                    $accy_neg+=$this->plots[$j]->coords[0][$i];
     1011                    if(  $this->plots[$j]->valuepos=='center' ) {
     1012                        $y = $accyt-($accyt-$yt)/2;
     1013                    }
     1014                    elseif( $this->plots[$j]->valuepos=='bottom' ) {
     1015                        $y = $accyt;
     1016                    }
     1017                    else {
     1018                        $y = $accyt-($accyt-$yt);
     1019                    }
     1020                    if(  $this->plots[$j]->valuepos=='center' ) {
     1021                        $this->plots[$j]->value->SetAlign("center","center");
     1022                        $this->plots[$j]->value->SetMargin(0);
     1023                    }
     1024                    elseif( $this->plots[$j]->valuepos=='bottom' ) {
     1025                        $this->plots[$j]->value->SetAlign('center',$j==0 ? 'bottom':'top');
     1026                        $this->plots[$j]->value->SetMargin(-2);
     1027                    }
     1028                    else {
     1029                        $this->plots[$j]->value->SetAlign('center','bottom');
     1030                        $this->plots[$j]->value->SetMargin(-1);
     1031                    }
     1032                }       
     1033                $this->plots[$j]->value->Stroke($img,$this->plots[$j]->coords[0][$i],$x,$y);
     1034            }
     1035
     1036        }
     1037        return true;
    11851038    }
    11861039} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_canvas.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_CANVAS.PHP
    4  // Description: Canvas drawing extension for JpGraph
    5  // Created:     2001-01-08
    6  // Ver:         $Id: jpgraph_canvas.php 1923 2010-01-11 13:48:49Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_CANVAS.PHP
     4// Description: Canvas drawing extension for JpGraph
     5// Created:     2001-01-08
     6// Ver:         $Id: jpgraph_canvas.php 781 2006-10-08 08:07:47Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212//===================================================
     
    1616// primitives. Useful to auickoly produce some arbitrary
    1717// graphic which benefits from all the functionality in the
    18 // graph liek caching for example.
     18// graph liek caching for example. 
    1919//===================================================
    2020class CanvasGraph extends Graph {
    21     //---------------
    22     // CONSTRUCTOR
    23     function __construct($aWidth=300,$aHeight=200,$aCachedName="",$timeout=0,$inline=1) {
    24         parent::__construct($aWidth,$aHeight,$aCachedName,$timeout,$inline);
     21//---------------
     22// CONSTRUCTOR
     23    function CanvasGraph($aWidth=300,$aHeight=200,$aCachedName="",$timeout=0,$inline=1) {
     24        $this->Graph($aWidth,$aHeight,$aCachedName,$timeout,$inline);
    2525    }
    2626
    27     //---------------
    28     // PUBLIC METHODS
     27//---------------
     28// PUBLIC METHODS       
    2929
    3030    function InitFrame() {
    31         $this->StrokePlotArea();
     31        $this->StrokePlotArea();
    3232    }
    3333
    3434    // Method description
    3535    function Stroke($aStrokeFileName="") {
    36         if( $this->texts != null ) {
    37             for($i=0; $i < count($this->texts); ++$i) {
    38                 $this->texts[$i]->Stroke($this->img);
    39             }
    40         }
    41         if( $this->iTables !== null ) {
    42             for($i=0; $i < count($this->iTables); ++$i) {
    43                 $this->iTables[$i]->Stroke($this->img);
    44             }
    45         }
    46         $this->StrokeTitles();
     36        if( $this->texts != null ) {
     37            for($i=0; $i < count($this->texts); ++$i) {
     38                $this->texts[$i]->Stroke($this->img);
     39            }
     40        }               
     41        if( $this->iTables !== null ) {
     42            for($i=0; $i < count($this->iTables); ++$i) {
     43                $this->iTables[$i]->Stroke($this->img);
     44            }   
     45        }
     46        $this->StrokeTitles();
    4747
    48         // If the filename is the predefined value = '_csim_special_'
    49         // we assume that the call to stroke only needs to do enough
    50         // to correctly generate the CSIM maps.
    51         // We use this variable to skip things we don't strictly need
    52         // to do to generate the image map to improve performance
    53         // a best we can. Therefor you will see a lot of tests !$_csim in the
    54         // code below.
    55         $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
     48        // If the filename is the predefined value = '_csim_special_'
     49        // we assume that the call to stroke only needs to do enough
     50        // to correctly generate the CSIM maps.
     51        // We use this variable to skip things we don't strictly need
     52        // to do to generate the image map to improve performance
     53        // a best we can. Therefor you will see a lot of tests !$_csim in the
     54        // code below.
     55        $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
    5656
    57         // We need to know if we have stroked the plot in the
    58         // GetCSIMareas. Otherwise the CSIM hasn't been generated
    59         // and in the case of GetCSIM called before stroke to generate
    60         // CSIM without storing an image to disk GetCSIM must call Stroke.
    61         $this->iHasStroked = true;
     57        // We need to know if we have stroked the plot in the
     58        // GetCSIMareas. Otherwise the CSIM hasn't been generated
     59        // and in the case of GetCSIM called before stroke to generate
     60        // CSIM without storing an image to disk GetCSIM must call Stroke.
     61        $this->iHasStroked = true;
    6262
    63         if( !$_csim ) {
     63        if( !$_csim ) {
    6464
    65             // Should we do any final image transformation
    66             if( $this->iImgTrans ) {
    67                 if( !class_exists('ImgTrans',false) ) {
    68                     require_once('jpgraph_imgtrans.php');
    69                 }
     65            // Should we do any final image transformation
     66            if( $this->iImgTrans ) {
     67                if( !class_exists('ImgTrans') ) {
     68                    require_once('jpgraph_imgtrans.php');
     69                }
     70               
     71                $tform = new ImgTrans($this->img->img);
     72                $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
     73                                                 $this->iImgTransDirection,$this->iImgTransHighQ,
     74                                                 $this->iImgTransMinSize,$this->iImgTransFillColor,
     75                                                 $this->iImgTransBorder);
     76            }
     77       
    7078
    71                 $tform = new ImgTrans($this->img->img);
    72                 $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
    73                 $this->iImgTransDirection,$this->iImgTransHighQ,
    74                 $this->iImgTransMinSize,$this->iImgTransFillColor,
    75                 $this->iImgTransBorder);
    76             }
    77 
    78 
    79             // If the filename is given as the special _IMG_HANDLER
    80             // then the image handler is returned and the image is NOT
    81             // streamed back
    82             if( $aStrokeFileName == _IMG_HANDLER ) {
    83                 return $this->img->img;
    84             }
    85             else {
    86                 // Finally stream the generated picture
    87                 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
    88                 return true;
    89             }
    90         }
     79            // If the filename is given as the special _IMG_HANDLER
     80            // then the image handler is returned and the image is NOT
     81            // streamed back
     82            if( $aStrokeFileName == _IMG_HANDLER ) {
     83                return $this->img->img;
     84            }
     85            else {
     86                // Finally stream the generated picture                                 
     87                $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
     88                return true;
     89            }
     90        }
    9191    }
    9292} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_canvtools.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_CANVTOOLS.PHP
    4  // Description: Some utilities for text and shape drawing on a canvas
    5  // Created:     2002-08-23
    6  // Ver:         $Id: jpgraph_canvtools.php 1857 2009-09-28 14:38:14Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_CANVTOOLS.PHP
     4// Description: Some utilities for text and shape drawing on a canvas
     5// Created:     2002-08-23
     6// Ver:         $Id: jpgraph_canvtools.php 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212define('CORNER_TOPLEFT',0);
     
    2121// can abstract away with absolute pixels
    2222//===================================================
    23 
     23 
    2424class CanvasScale {
    2525    private $g;
     
    2727    private $ixmin=0,$ixmax=10,$iymin=0,$iymax=10;
    2828
    29     function __construct($graph,$xmin=0,$xmax=10,$ymin=0,$ymax=10) {
    30         $this->g = $graph;
    31         $this->w = $graph->img->width;
    32         $this->h = $graph->img->height;
    33         $this->ixmin = $xmin;
    34         $this->ixmax = $xmax;
    35         $this->iymin = $ymin;
    36         $this->iymax = $ymax;
    37     }
    38 
     29    function CanvasScale($graph,$xmin=0,$xmax=10,$ymin=0,$ymax=10) {
     30        $this->g = $graph;
     31        $this->w = $graph->img->width;
     32        $this->h = $graph->img->height;
     33        $this->ixmin = $xmin;
     34        $this->ixmax = $xmax;
     35        $this->iymin = $ymin;
     36        $this->iymax = $ymax;
     37    }
     38   
    3939    function Set($xmin=0,$xmax=10,$ymin=0,$ymax=10) {
    40         $this->ixmin = $xmin;
    41         $this->ixmax = $xmax;
    42         $this->iymin = $ymin;
    43         $this->iymax = $ymax;
    44     }
    45 
    46     function Get() {
    47         return array($this->ixmin,$this->ixmax,$this->iymin,$this->iymax);
     40        $this->ixmin = $xmin;
     41        $this->ixmax = $xmax;
     42        $this->iymin = $ymin;
     43        $this->iymax = $ymax;
    4844    }
    4945
    5046    function Translate($x,$y) {
    51         $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
    52         $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
    53         return array($xp,$yp);
     47        $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
     48        $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
     49        return array($xp,$yp);
    5450    }
    5551
    5652    function TranslateX($x) {
    57         $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
    58         return $xp;
     53        $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
     54        return $xp;
    5955    }
    6056
    6157    function TranslateY($y) {
    62         $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
    63         return $yp;
     58        $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
     59        return $yp;
    6460    }
    6561
     
    7470    private $img,$scale;
    7571
    76     function __construct($aGraph,$scale) {
    77         $this->img = $aGraph->img;
    78         $this->img->SetColor('black');
    79         $this->scale = $scale;
     72    function Shape($aGraph,$scale) {
     73        $this->img = $aGraph->img;
     74        $this->img->SetColor('black');
     75        $this->scale = $scale;
    8076    }
    8177
    8278    function SetColor($aColor) {
    83         $this->img->SetColor($aColor);
     79        $this->img->SetColor($aColor);
    8480    }
    8581
    8682    function Line($x1,$y1,$x2,$y2) {
    87         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    88         list($x2,$y2) = $this->scale->Translate($x2,$y2);
    89         $this->img->Line($x1,$y1,$x2,$y2);
    90     }
    91 
    92     function SetLineWeight($aWeight) {
    93         $this->img->SetLineWeight($aWeight);
     83        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     84        list($x2,$y2) = $this->scale->Translate($x2,$y2);
     85        $this->img->Line($x1,$y1,$x2,$y2);
    9486    }
    9587
    9688    function Polygon($p,$aClosed=false) {
    97         $n=count($p);
    98         for($i=0; $i < $n; $i+=2 ) {
    99             $p[$i]   = $this->scale->TranslateX($p[$i]);
    100             $p[$i+1] = $this->scale->TranslateY($p[$i+1]);
    101         }
    102         $this->img->Polygon($p,$aClosed);
     89        $n=count($p);
     90        for($i=0; $i < $n; $i+=2 ) {
     91           $p[$i]   = $this->scale->TranslateX($p[$i]);
     92           $p[$i+1] = $this->scale->TranslateY($p[$i+1]);
     93        }
     94        $this->img->Polygon($p,$aClosed);
    10395    }
    10496
    10597    function FilledPolygon($p) {
    106         $n=count($p);
    107         for($i=0; $i < $n; $i+=2 ) {
    108             $p[$i]   = $this->scale->TranslateX($p[$i]);
    109             $p[$i+1] = $this->scale->TranslateY($p[$i+1]);
    110         }
    111         $this->img->FilledPolygon($p);
    112     }
    113 
     98        $n=count($p);
     99        for($i=0; $i < $n; $i+=2 ) {
     100           $p[$i]   = $this->scale->TranslateX($p[$i]);
     101           $p[$i+1] = $this->scale->TranslateY($p[$i+1]);
     102        }
     103        $this->img->FilledPolygon($p);
     104    }
     105   
    114106
    115107    // Draw a bezier curve with defining points in the $aPnts array
     
    120112    // 6=x3, 7=y3
    121113    function Bezier($p,$aSteps=40) {
    122         $x0 = $p[0];
    123         $y0 = $p[1];
    124         // Calculate coefficients
    125         $cx = 3*($p[2]-$p[0]);
    126         $bx = 3*($p[4]-$p[2])-$cx;
    127         $ax = $p[6]-$p[0]-$cx-$bx;
    128         $cy = 3*($p[3]-$p[1]);
    129         $by = 3*($p[5]-$p[3])-$cy;
    130         $ay = $p[7]-$p[1]-$cy-$by;
    131 
    132         // Step size
    133         $delta = 1.0/$aSteps;
    134 
    135         $x_old = $x0;
    136         $y_old = $y0;
    137         for($t=$delta; $t<=1.0; $t+=$delta) {
    138             $tt = $t*$t; $ttt=$tt*$t;
    139             $x  = $ax*$ttt + $bx*$tt + $cx*$t + $x0;
    140             $y = $ay*$ttt + $by*$tt + $cy*$t + $y0;
    141             $this->Line($x_old,$y_old,$x,$y);
    142             $x_old = $x;
    143             $y_old = $y;
    144         }
    145         $this->Line($x_old,$y_old,$p[6],$p[7]);
     114        $x0 = $p[0];
     115        $y0 = $p[1];
     116        // Calculate coefficients
     117        $cx = 3*($p[2]-$p[0]);
     118        $bx = 3*($p[4]-$p[2])-$cx;
     119        $ax = $p[6]-$p[0]-$cx-$bx;
     120        $cy = 3*($p[3]-$p[1]);
     121        $by = 3*($p[5]-$p[3])-$cy;
     122        $ay = $p[7]-$p[1]-$cy-$by;
     123
     124        // Step size
     125        $delta = 1.0/$aSteps;
     126
     127        $x_old = $x0;
     128        $y_old = $y0;
     129        for($t=$delta; $t<=1.0; $t+=$delta) {
     130            $tt = $t*$t; $ttt=$tt*$t;
     131            $x  = $ax*$ttt + $bx*$tt + $cx*$t + $x0;
     132            $y = $ay*$ttt + $by*$tt + $cy*$t + $y0;
     133            $this->Line($x_old,$y_old,$x,$y);
     134            $x_old = $x;
     135            $y_old = $y;
     136        }
     137        $this->Line($x_old,$y_old,$p[6],$p[7]);
    146138    }
    147139
    148140    function Rectangle($x1,$y1,$x2,$y2) {
    149         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    150         list($x2,$y2)   = $this->scale->Translate($x2,$y2);
    151         $this->img->Rectangle($x1,$y1,$x2,$y2);
     141        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     142        list($x2,$y2)   = $this->scale->Translate($x2,$y2);
     143        $this->img->Rectangle($x1,$y1,$x2,$y2);
    152144    }
    153145
    154146    function FilledRectangle($x1,$y1,$x2,$y2) {
    155         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    156         list($x2,$y2)   = $this->scale->Translate($x2,$y2);
    157         $this->img->FilledRectangle($x1,$y1,$x2,$y2);
    158     }
    159 
     147        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     148        list($x2,$y2)   = $this->scale->Translate($x2,$y2);
     149        $this->img->FilledRectangle($x1,$y1,$x2,$y2);
     150    }
     151   
    160152    function Circle($x1,$y1,$r) {
    161         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    162         if( $r >= 0 )
    163         $r   = $this->scale->TranslateX($r);
    164         else
    165         $r = -$r;
    166         $this->img->Circle($x1,$y1,$r);
     153        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     154        if( $r >= 0 )
     155            $r   = $this->scale->TranslateX($r);
     156        else
     157            $r = -$r;
     158        $this->img->Circle($x1,$y1,$r);
    167159    }
    168160
    169161    function FilledCircle($x1,$y1,$r) {
    170         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    171         if( $r >= 0 )
    172         $r   = $this->scale->TranslateX($r);
    173         else
    174         $r = -$r;
    175         $this->img->FilledCircle($x1,$y1,$r);
    176     }
    177 
    178     function RoundedRectangle($x1,$y1,$x2,$y2,$r=null) {
    179         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    180         list($x2,$y2)   = $this->scale->Translate($x2,$y2);
    181 
    182         if( $r == null )
    183         $r = 5;
    184         elseif( $r >= 0 )
    185         $r = $this->scale->TranslateX($r);
    186         else
    187         $r = -$r;
    188         $this->img->RoundedRectangle($x1,$y1,$x2,$y2,$r);
    189     }
    190 
    191     function FilledRoundedRectangle($x1,$y1,$x2,$y2,$r=null) {
    192         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    193         list($x2,$y2)   = $this->scale->Translate($x2,$y2);
    194 
    195         if( $r == null )
    196         $r = 5;
    197         elseif( $r > 0 )
    198         $r = $this->scale->TranslateX($r);
    199         else
    200         $r = -$r;
    201         $this->img->FilledRoundedRectangle($x1,$y1,$x2,$y2,$r);
     162        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     163        if( $r >= 0 )
     164            $r   = $this->scale->TranslateX($r);
     165        else
     166            $r = -$r;
     167        $this->img->FilledCircle($x1,$y1,$r);
     168    }
     169
     170    function RoundedRectangle($x1,$y1,$x2,$y2,$r=null) {   
     171        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     172        list($x2,$y2)   = $this->scale->Translate($x2,$y2);
     173
     174        if( $r == null )
     175            $r = 5;
     176        elseif( $r >= 0 )
     177            $r = $this->scale->TranslateX($r);
     178        else
     179            $r = -$r;
     180        $this->img->RoundedRectangle($x1,$y1,$x2,$y2,$r);
     181    }
     182
     183    function FilledRoundedRectangle($x1,$y1,$x2,$y2,$r=null) {   
     184        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     185        list($x2,$y2)   = $this->scale->Translate($x2,$y2);
     186
     187        if( $r == null )
     188            $r = 5;
     189        elseif( $r > 0 )
     190            $r = $this->scale->TranslateX($r);
     191        else
     192            $r = -$r;
     193        $this->img->FilledRoundedRectangle($x1,$y1,$x2,$y2,$r);   
    202194    }
    203195
    204196    function ShadowRectangle($x1,$y1,$x2,$y2,$fcolor=false,$shadow_width=null,$shadow_color=array(102,102,102)) {
    205         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    206         list($x2,$y2) = $this->scale->Translate($x2,$y2);
    207         if( $shadow_width == null )
    208         $shadow_width=4;
    209         else
    210         $shadow_width=$this->scale->TranslateX($shadow_width);
    211         $this->img->ShadowRectangle($x1,$y1,$x2,$y2,$fcolor,$shadow_width,$shadow_color);
     197        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     198        list($x2,$y2) = $this->scale->Translate($x2,$y2);
     199        if( $shadow_width == null )
     200            $shadow_width=4;
     201        else
     202            $shadow_width=$this->scale->TranslateX($shadow_width);
     203        $this->img->ShadowRectangle($x1,$y1,$x2,$y2,$fcolor,$shadow_width,$shadow_color);
    212204    }
    213205
    214206    function SetTextAlign($halign,$valign="bottom") {
    215         $this->img->SetTextAlign($halign,$valign="bottom");
     207        $this->img->SetTextAlign($halign,$valign="bottom");
    216208    }
    217209
    218210    function StrokeText($x1,$y1,$txt,$dir=0,$paragraph_align="left") {
    219         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    220         $this->img->StrokeText($x1,$y1,$txt,$dir,$paragraph_align);
     211        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     212        $this->img->StrokeText($x1,$y1,$txt,$dir,$paragraph_align);
    221213    }
    222214
     
    225217    // 0=Top left, 1=top right, 2=bottom right, 3=bottom left
    226218    function IndentedRectangle($xt,$yt,$w,$h,$iw=0,$ih=0,$aCorner=3,$aFillColor="",$r=4) {
    227 
    228         list($xt,$yt) = $this->scale->Translate($xt,$yt);
    229         list($w,$h)   = $this->scale->Translate($w,$h);
    230         list($iw,$ih) = $this->scale->Translate($iw,$ih);
    231 
    232         $xr = $xt + $w - 0;
    233         $yl = $yt + $h - 0;
    234 
    235         switch( $aCorner ) {
    236             case 0: // Upper left
    237                 
    238                 // Bottom line, left &  right arc
    239                 $this->img->Line($xt+$r,$yl,$xr-$r,$yl);
    240                 $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
    241                 $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
    242 
    243                 // Right line, Top right arc
    244                 $this->img->Line($xr,$yt+$r,$xr,$yl-$r);
    245                 $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
    246 
    247                 // Top line, Top left arc
    248                 $this->img->Line($xt+$iw+$r,$yt,$xr-$r,$yt);
    249                 $this->img->Arc($xt+$iw+$r,$yt+$r,$r*2,$r*2,180,270);
    250 
    251                 // Left line
    252                 $this->img->Line($xt,$yt+$ih+$r,$xt,$yl-$r);
    253 
    254                 // Indent horizontal, Lower left arc
    255                 $this->img->Line($xt+$r,$yt+$ih,$xt+$iw-$r,$yt+$ih);
    256                 $this->img->Arc($xt+$r,$yt+$ih+$r,$r*2,$r*2,180,270);
    257 
    258                 // Indent vertical, Indent arc
    259                 $this->img->Line($xt+$iw,$yt+$r,$xt+$iw,$yt+$ih-$r);
    260                 $this->img->Arc($xt+$iw-$r,$yt+$ih-$r,$r*2,$r*2,0,90);
    261 
    262                 if( $aFillColor != '' ) {
    263                     $bc = $this->img->current_color_name;
    264                     $this->img->PushColor($aFillColor);
    265                     $this->img->FillToBorder($xr-$r,$yl-$r,$bc);
    266                     $this->img->PopColor();
    267                 }
    268 
    269                 break;
    270 
    271             case 1: // Upper right
    272 
    273                 // Bottom line, left &  right arc
    274                 $this->img->Line($xt+$r,$yl,$xr-$r,$yl);
    275                 $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
    276                 $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
    277 
    278                 // Left line, Top left arc
    279                 $this->img->Line($xt,$yt+$r,$xt,$yl-$r);
    280                 $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
    281 
    282                 // Top line, Top right arc
    283                 $this->img->Line($xt+$r,$yt,$xr-$iw-$r,$yt);
    284                 $this->img->Arc($xr-$iw-$r,$yt+$r,$r*2,$r*2,270,360);
    285 
    286                 // Right line
    287                 $this->img->Line($xr,$yt+$ih+$r,$xr,$yl-$r);
    288 
    289                 // Indent horizontal, Lower right arc
    290                 $this->img->Line($xr-$iw+$r,$yt+$ih,$xr-$r,$yt+$ih);
    291                 $this->img->Arc($xr-$r,$yt+$ih+$r,$r*2,$r*2,270,360);
    292 
    293                 // Indent vertical, Indent arc
    294                 $this->img->Line($xr-$iw,$yt+$r,$xr-$iw,$yt+$ih-$r);
    295                 $this->img->Arc($xr-$iw+$r,$yt+$ih-$r,$r*2,$r*2,90,180);
    296 
    297                 if( $aFillColor != '' ) {
    298                     $bc = $this->img->current_color_name;
    299                     $this->img->PushColor($aFillColor);
    300                     $this->img->FillToBorder($xt+$r,$yl-$r,$bc);
    301                     $this->img->PopColor();
    302                 }
    303 
    304                 break;
    305 
    306             case 2: // Lower right
    307                 // Top line, Top left & Top right arc
    308                 $this->img->Line($xt+$r,$yt,$xr-$r,$yt);
    309                 $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
    310                 $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
    311 
    312                 // Left line, Bottom left arc
    313                 $this->img->Line($xt,$yt+$r,$xt,$yl-$r);
    314                 $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
    315 
    316                 // Bottom line, Bottom right arc
    317                 $this->img->Line($xt+$r,$yl,$xr-$iw-$r,$yl);
    318                 $this->img->Arc($xr-$iw-$r,$yl-$r,$r*2,$r*2,0,90);
    319 
    320                 // Right line
    321                 $this->img->Line($xr,$yt+$r,$xr,$yl-$ih-$r);
    322                 
    323                 // Indent horizontal, Lower right arc
    324                 $this->img->Line($xr-$r,$yl-$ih,$xr-$iw+$r,$yl-$ih);
    325                 $this->img->Arc($xr-$r,$yl-$ih-$r,$r*2,$r*2,0,90);
    326 
    327                 // Indent vertical, Indent arc
    328                 $this->img->Line($xr-$iw,$yl-$r,$xr-$iw,$yl-$ih+$r);
    329                 $this->img->Arc($xr-$iw+$r,$yl-$ih+$r,$r*2,$r*2,180,270);
    330 
    331                 if( $aFillColor != '' ) {
    332                     $bc = $this->img->current_color_name;
    333                     $this->img->PushColor($aFillColor);
    334                     $this->img->FillToBorder($xt+$r,$yt+$r,$bc);
    335                     $this->img->PopColor();
    336                 }
    337 
    338                 break;
    339 
    340             case 3: // Lower left
    341                 // Top line, Top left & Top right arc
    342                 $this->img->Line($xt+$r,$yt,$xr-$r,$yt);
    343                 $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
    344                 $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
    345 
    346                 // Right line, Bottom right arc
    347                 $this->img->Line($xr,$yt+$r,$xr,$yl-$r);
    348                 $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
    349 
    350                 // Bottom line, Bottom left arc
    351                 $this->img->Line($xt+$iw+$r,$yl,$xr-$r,$yl);
    352                 $this->img->Arc($xt+$iw+$r,$yl-$r,$r*2,$r*2,90,180);
    353 
    354                 // Left line
    355                 $this->img->Line($xt,$yt+$r,$xt,$yl-$ih-$r);
    356                 
    357                 // Indent horizontal, Lower left arc
    358                 $this->img->Line($xt+$r,$yl-$ih,$xt+$iw-$r,$yl-$ih);
    359                 $this->img->Arc($xt+$r,$yl-$ih-$r,$r*2,$r*2,90,180);
    360 
    361                 // Indent vertical, Indent arc
    362                 $this->img->Line($xt+$iw,$yl-$ih+$r,$xt+$iw,$yl-$r);
    363                 $this->img->Arc($xt+$iw-$r,$yl-$ih+$r,$r*2,$r*2,270,360);
    364 
    365                 if( $aFillColor != '' ) {
    366                     $bc = $this->img->current_color_name;
    367                     $this->img->PushColor($aFillColor);
    368                     $this->img->FillToBorder($xr-$r,$yt+$r,$bc);
    369                     $this->img->PopColor();
    370                 }
    371 
    372                 break;
    373         }
     219   
     220        list($xt,$yt) = $this->scale->Translate($xt,$yt);
     221        list($w,$h)   = $this->scale->Translate($w,$h);
     222        list($iw,$ih) = $this->scale->Translate($iw,$ih);
     223       
     224        $xr = $xt + $w - 0;
     225        $yl = $yt + $h - 0;
     226
     227        switch( $aCorner ) {
     228            case 0: // Upper left
     229           
     230                // Bottom line, left &  right arc
     231                $this->img->Line($xt+$r,$yl,$xr-$r,$yl);
     232                $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
     233                $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
     234
     235                // Right line, Top right arc
     236                $this->img->Line($xr,$yt+$r,$xr,$yl-$r);
     237                $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
     238
     239                // Top line, Top left arc
     240                $this->img->Line($xt+$iw+$r,$yt,$xr-$r,$yt);
     241                $this->img->Arc($xt+$iw+$r,$yt+$r,$r*2,$r*2,180,270);
     242
     243                // Left line
     244                $this->img->Line($xt,$yt+$ih+$r,$xt,$yl-$r);
     245
     246                // Indent horizontal, Lower left arc
     247                $this->img->Line($xt+$r,$yt+$ih,$xt+$iw-$r,$yt+$ih);
     248                $this->img->Arc($xt+$r,$yt+$ih+$r,$r*2,$r*2,180,270);
     249
     250                // Indent vertical, Indent arc
     251                $this->img->Line($xt+$iw,$yt+$r,$xt+$iw,$yt+$ih-$r);
     252                $this->img->Arc($xt+$iw-$r,$yt+$ih-$r,$r*2,$r*2,0,90);
     253
     254                if( $aFillColor != '' ) {
     255                    $bc = $this->img->current_color_name;
     256                    $this->img->PushColor($aFillColor);
     257                    $this->img->FillToBorder($xr-$r,$yl-$r,$bc);
     258                    $this->img->PopColor();
     259                }
     260
     261                break;
     262
     263            case 1: // Upper right
     264
     265                // Bottom line, left &  right arc
     266                $this->img->Line($xt+$r,$yl,$xr-$r,$yl);
     267                $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
     268                $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
     269
     270                // Left line, Top left arc
     271                $this->img->Line($xt,$yt+$r,$xt,$yl-$r);
     272                $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
     273
     274                // Top line, Top right arc
     275                $this->img->Line($xt+$r,$yt,$xr-$iw-$r,$yt);
     276                $this->img->Arc($xr-$iw-$r,$yt+$r,$r*2,$r*2,270,360);
     277
     278                // Right line
     279                $this->img->Line($xr,$yt+$ih+$r,$xr,$yl-$r);
     280
     281                // Indent horizontal, Lower right arc
     282                $this->img->Line($xr-$iw+$r,$yt+$ih,$xr-$r,$yt+$ih);
     283                $this->img->Arc($xr-$r,$yt+$ih+$r,$r*2,$r*2,270,360);
     284
     285                // Indent vertical, Indent arc
     286                $this->img->Line($xr-$iw,$yt+$r,$xr-$iw,$yt+$ih-$r);
     287                $this->img->Arc($xr-$iw+$r,$yt+$ih-$r,$r*2,$r*2,90,180);
     288
     289                if( $aFillColor != '' ) {
     290                    $bc = $this->img->current_color_name;
     291                    $this->img->PushColor($aFillColor);
     292                    $this->img->FillToBorder($xt+$r,$yl-$r,$bc);
     293                    $this->img->PopColor();
     294                }
     295
     296                break;
     297
     298            case 2: // Lower right
     299                // Top line, Top left & Top right arc
     300                $this->img->Line($xt+$r,$yt,$xr-$r,$yt);
     301                $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
     302                $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
     303
     304                // Left line, Bottom left arc
     305                $this->img->Line($xt,$yt+$r,$xt,$yl-$r);
     306                $this->img->Arc($xt+$r,$yl-$r,$r*2,$r*2,90,180);
     307
     308                // Bottom line, Bottom right arc
     309                $this->img->Line($xt+$r,$yl,$xr-$iw-$r,$yl);
     310                $this->img->Arc($xr-$iw-$r,$yl-$r,$r*2,$r*2,0,90);
     311
     312                // Right line
     313                $this->img->Line($xr,$yt+$r,$xr,$yl-$ih-$r);
     314           
     315                // Indent horizontal, Lower right arc
     316                $this->img->Line($xr-$r,$yl-$ih,$xr-$iw+$r,$yl-$ih);
     317                $this->img->Arc($xr-$r,$yl-$ih-$r,$r*2,$r*2,0,90);
     318
     319                // Indent vertical, Indent arc
     320                $this->img->Line($xr-$iw,$yl-$r,$xr-$iw,$yl-$ih+$r);
     321                $this->img->Arc($xr-$iw+$r,$yl-$ih+$r,$r*2,$r*2,180,270);
     322
     323                if( $aFillColor != '' ) {
     324                    $bc = $this->img->current_color_name;
     325                    $this->img->PushColor($aFillColor);
     326                    $this->img->FillToBorder($xt+$r,$yt+$r,$bc);
     327                    $this->img->PopColor();
     328                }
     329
     330                break;
     331
     332            case 3: // Lower left
     333                // Top line, Top left & Top right arc
     334                $this->img->Line($xt+$r,$yt,$xr-$r,$yt);
     335                $this->img->Arc($xt+$r,$yt+$r,$r*2,$r*2,180,270);
     336                $this->img->Arc($xr-$r,$yt+$r,$r*2,$r*2,270,360);
     337
     338                // Right line, Bottom right arc
     339                $this->img->Line($xr,$yt+$r,$xr,$yl-$r);
     340                $this->img->Arc($xr-$r,$yl-$r,$r*2,$r*2,0,90);
     341
     342                // Bottom line, Bottom left arc
     343                $this->img->Line($xt+$iw+$r,$yl,$xr-$r,$yl);
     344                $this->img->Arc($xt+$iw+$r,$yl-$r,$r*2,$r*2,90,180);
     345
     346                // Left line
     347                $this->img->Line($xt,$yt+$r,$xt,$yl-$ih-$r);
     348           
     349                // Indent horizontal, Lower left arc
     350                $this->img->Line($xt+$r,$yl-$ih,$xt+$iw-$r,$yl-$ih);
     351                $this->img->Arc($xt+$r,$yl-$ih-$r,$r*2,$r*2,90,180);
     352
     353                // Indent vertical, Indent arc
     354                $this->img->Line($xt+$iw,$yl-$ih+$r,$xt+$iw,$yl-$r);
     355                $this->img->Arc($xt+$iw-$r,$yl-$ih+$r,$r*2,$r*2,270,360);
     356
     357                if( $aFillColor != '' ) {
     358                    $bc = $this->img->current_color_name;
     359                    $this->img->PushColor($aFillColor);
     360                    $this->img->FillToBorder($xr-$r,$yt+$r,$bc);
     361                    $this->img->PopColor();
     362                }
     363
     364                break;
     365        }
    374366    }
    375367}
     
    378370//===================================================
    379371// CLASS RectangleText
    380 // Description: Draws a text paragraph inside a
     372// Description: Draws a text paragraph inside a 
    381373// rounded, possible filled, rectangle.
    382374//===================================================
     
    388380    private $iShadowWidth=3,$iShadowColor='';
    389381
    390     function __construct($aTxt='',$xl=0,$yt=0,$w=0,$h=0) {
    391         $this->iTxt = new Text($aTxt);
    392         $this->ix = $xl;
    393         $this->iy = $yt;
    394         $this->iw = $w;
    395         $this->ih = $h;
    396     }
    397 
     382    function CanvasRectangleText($aTxt='',$xl=0,$yt=0,$w=0,$h=0) {
     383        $this->iTxt = new Text($aTxt);
     384        $this->ix = $xl;
     385        $this->iy = $yt;
     386        $this->iw = $w;
     387        $this->ih = $h;
     388    }
     389 
    398390    function SetShadow($aColor='gray',$aWidth=3) {
    399         $this->iShadowColor = $aColor;
    400         $this->iShadowWidth = $aWidth;
     391        $this->iShadowColor = $aColor;
     392        $this->iShadowWidth = $aWidth;
    401393    }
    402394
    403395    function SetFont($FontFam,$aFontStyle,$aFontSize=12) {
    404         $this->iTxt->SetFont($FontFam,$aFontStyle,$aFontSize);
     396        $this->iTxt->SetFont($FontFam,$aFontStyle,$aFontSize);
    405397    }
    406398
    407399    function SetTxt($aTxt) {
    408         $this->iTxt->Set($aTxt);
     400        $this->iTxt->Set($aTxt);
    409401    }
    410402
    411403    function ParagraphAlign($aParaAlign) {
    412         $this->iParaAlign = $aParaAlign;
     404        $this->iParaAlign = $aParaAlign;
    413405    }
    414406
    415407    function SetFillColor($aFillColor) {
    416         $this->iFillColor = $aFillColor;
     408        $this->iFillColor = $aFillColor;
    417409    }
    418410
    419411    function SetAutoMargin($aMargin) {
    420         $this->iAutoBoxMargin=$aMargin;
     412        $this->iAutoBoxMargin=$aMargin;
    421413    }
    422414
    423415    function SetColor($aColor) {
    424         $this->iColor = $aColor;
     416        $this->iColor = $aColor;
    425417    }
    426418
    427419    function SetFontColor($aColor) {
    428         $this->iFontColor = $aColor;
     420        $this->iFontColor = $aColor;
    429421    }
    430422
    431423    function SetPos($xl=0,$yt=0,$w=0,$h=0) {
    432         $this->ix = $xl;
    433         $this->iy = $yt;
    434         $this->iw = $w;
    435         $this->ih = $h;
     424        $this->ix = $xl;
     425        $this->iy = $yt;
     426        $this->iw = $w;
     427        $this->ih = $h;
    436428    }
    437429
    438430    function Pos($xl=0,$yt=0,$w=0,$h=0) {
    439         $this->ix = $xl;
    440         $this->iy = $yt;
    441         $this->iw = $w;
    442         $this->ih = $h;
     431        $this->ix = $xl;
     432        $this->iy = $yt;
     433        $this->iw = $w;
     434        $this->ih = $h;
    443435    }
    444436
    445437    function Set($aTxt,$xl,$yt,$w=0,$h=0) {
    446         $this->iTxt->Set($aTxt);
    447         $this->ix = $xl;
    448         $this->iy = $yt;
    449         $this->iw = $w;
    450         $this->ih = $h;
     438        $this->iTxt->Set($aTxt);
     439        $this->ix = $xl;
     440        $this->iy = $yt;
     441        $this->iw = $w;
     442        $this->ih = $h;
    451443    }
    452444
    453445    function SetCornerRadius($aRad=5) {
    454         $this->ir = $aRad;
     446        $this->ir = $aRad;
    455447    }
    456448
    457449    function Stroke($aImg,$scale) {
    458 
    459         // If coordinates are specifed as negative this means we should
    460         // treat them as abolsute (pixels) coordinates
    461         if( $this->ix > 0 ) {
    462             $this->ix = $scale->TranslateX($this->ix) ;
    463         }
    464         else {
    465             $this->ix = -$this->ix;
    466         }
    467 
    468         if( $this->iy > 0 ) {
    469             $this->iy = $scale->TranslateY($this->iy) ;
    470         }
    471         else {
    472             $this->iy = -$this->iy;
    473         }
    474         
    475         list($this->iw,$this->ih) = $scale->Translate($this->iw,$this->ih) ;
    476 
    477         if( $this->iw == 0 )
    478         $this->iw = round($this->iTxt->GetWidth($aImg) + $this->iAutoBoxMargin);
    479         if( $this->ih == 0 ) {
    480             $this->ih = round($this->iTxt->GetTextHeight($aImg) + $this->iAutoBoxMargin);
    481         }
    482 
    483         if( $this->iShadowColor != '' ) {
    484             $aImg->PushColor($this->iShadowColor);
    485             $aImg->FilledRoundedRectangle($this->ix+$this->iShadowWidth,
    486             $this->iy+$this->iShadowWidth,
    487             $this->ix+$this->iw-1+$this->iShadowWidth,
    488             $this->iy+$this->ih-1+$this->iShadowWidth,
    489             $this->ir);
    490             $aImg->PopColor();
    491         }
    492 
    493         if( $this->iFillColor != '' ) {
    494             $aImg->PushColor($this->iFillColor);
    495             $aImg->FilledRoundedRectangle($this->ix,$this->iy,
    496             $this->ix+$this->iw-1,
    497             $this->iy+$this->ih-1,
    498             $this->ir);
    499             $aImg->PopColor();
    500         }
    501 
    502         if( $this->iColor != '' ) {
    503             $aImg->PushColor($this->iColor);
    504             $aImg->RoundedRectangle($this->ix,$this->iy,
    505             $this->ix+$this->iw-1,
    506             $this->iy+$this->ih-1,
    507             $this->ir);
    508             $aImg->PopColor();
    509         }
    510 
    511         $this->iTxt->Align('center','center');
    512         $this->iTxt->ParagraphAlign($this->iParaAlign);
    513         $this->iTxt->SetColor($this->iFontColor);
    514         $this->iTxt->Stroke($aImg, $this->ix+$this->iw/2, $this->iy+$this->ih/2);
    515 
    516         return array($this->iw, $this->ih);
     450       
     451        // If coordinates are specifed as negative this means we should
     452        // treat them as abolsute (pixels) coordinates
     453        if( $this->ix > 0 ) {
     454            $this->ix = $scale->TranslateX($this->ix) ;
     455        }
     456        else {
     457            $this->ix = -$this->ix;
     458        }
     459
     460        if( $this->iy > 0 ) {
     461            $this->iy = $scale->TranslateY($this->iy) ;
     462        }
     463        else {
     464            $this->iy = -$this->iy;
     465        }
     466           
     467        list($this->iw,$this->ih) = $scale->Translate($this->iw,$this->ih) ;
     468
     469        if( $this->iw == 0 )
     470            $this->iw = round($this->iTxt->GetWidth($aImg) + $this->iAutoBoxMargin);
     471        if( $this->ih == 0 ) {
     472            $this->ih = round($this->iTxt->GetTextHeight($aImg) + $this->iAutoBoxMargin);
     473        }
     474
     475        if( $this->iShadowColor != '' ) {
     476            $aImg->PushColor($this->iShadowColor);
     477            $aImg->FilledRoundedRectangle($this->ix+$this->iShadowWidth,
     478                                          $this->iy+$this->iShadowWidth,
     479                                          $this->ix+$this->iw-1+$this->iShadowWidth,
     480                                          $this->iy+$this->ih-1+$this->iShadowWidth,
     481                                          $this->ir);
     482            $aImg->PopColor();     
     483        }
     484
     485        if( $this->iFillColor != '' ) {
     486            $aImg->PushColor($this->iFillColor);
     487            $aImg->FilledRoundedRectangle($this->ix,$this->iy,
     488                                          $this->ix+$this->iw-1,
     489                                          $this->iy+$this->ih-1,
     490                                          $this->ir);
     491            $aImg->PopColor();
     492        }
     493
     494        if( $this->iColor != '' ) {
     495            $aImg->PushColor($this->iColor);
     496            $aImg->RoundedRectangle($this->ix,$this->iy,
     497                                    $this->ix+$this->iw-1,
     498                                    $this->iy+$this->ih-1,
     499                                    $this->ir);
     500            $aImg->PopColor();
     501        }
     502       
     503        $this->iTxt->Align('center','center');
     504        $this->iTxt->ParagraphAlign($this->iParaAlign);
     505        $this->iTxt->SetColor($this->iFontColor);
     506        $this->iTxt->Stroke($aImg, $this->ix+$this->iw/2, $this->iy+$this->ih/2);
     507
     508        return array($this->iw, $this->ih);
    517509
    518510    }
  • trunk/client/modules/Elezioni/grafici/jpgraph_date.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_DATE.PHP
    4  // Description: Classes to handle Date scaling
    5  // Created:     2005-05-02
    6  // Ver:         $Id: jpgraph_date.php 1106 2009-02-22 20:16:35Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_DATE.PHP
     4// Description: Classes to handle Date scaling
     5// Created:     2005-05-02
     6// Ver:         $Id: jpgraph_date.php 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212define('HOURADJ_1',0+30);
     
    5252    private $iStartTimeAlign = false, $iEndTimeAlign = false;
    5353
    54     //---------------
    55     // CONSTRUCTOR
    56     function __construct($aMin=0,$aMax=0,$aType='x') {
    57         assert($aType=="x");
    58         assert($aMin<=$aMax);
    59 
    60         $this->type=$aType;
    61         $this->scale=array($aMin,$aMax);
    62         $this->world_size=$aMax-$aMin;
    63         $this->ticks = new LinearTicks();
    64         $this->intscale=true;
    65     }
    66 
    67 
    68     //------------------------------------------------------------------------------------------
    69     // Utility Function AdjDate()
    70     // Description: Will round a given time stamp to an even year, month or day
    71     // argument.
    72     //------------------------------------------------------------------------------------------
     54//---------------
     55// CONSTRUCTOR
     56    function DateScale($aMin=0,$aMax=0,$aType='x') {
     57        assert($aType=="x");
     58        assert($aMin<=$aMax);
     59               
     60        $this->type=$aType;
     61        $this->scale=array($aMin,$aMax);               
     62        $this->world_size=$aMax-$aMin; 
     63        $this->ticks = new LinearTicks();
     64        $this->intscale=true;
     65    }
     66
     67
     68//------------------------------------------------------------------------------------------
     69// Utility Function AdjDate()
     70// Description: Will round a given time stamp to an even year, month or day
     71// argument.
     72//------------------------------------------------------------------------------------------
    7373
    7474    function AdjDate($aTime,$aRound=0,$aYearType=false,$aMonthType=false,$aDayType=false) {
    75         $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
    76         $h=0;$i=0;$s=0;
    77         if( $aYearType !== false ) {
    78             $yearAdj = array(0=>1, 1=>2, 2=>5);
    79             if( $aRound == 0 ) {
    80                 $y = floor($y/$yearAdj[$aYearType])*$yearAdj[$aYearType];
    81             }
    82             else {
    83                 ++$y;
    84                 $y = ceil($y/$yearAdj[$aYearType])*$yearAdj[$aYearType];
    85             }
    86             $m=1;$d=1;
    87         }
    88         elseif( $aMonthType !== false ) {
    89             $monthAdj = array(0=>1, 1=>6);
    90             if( $aRound == 0 ) {
    91                 $m = floor($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType];
    92                 $d=1;
    93             }
    94             else {
    95                 ++$m;
    96                 $m = ceil($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType];
    97                 $d=1;
    98             }
    99         }
    100         elseif( $aDayType !== false ) {
    101             if( $aDayType == 0 ) {
    102                 if( $aRound == 1 ) {
    103                     //++$d;
    104                     $h=23;$i=59;$s=59;
    105                 }
    106             }
    107             else {
    108                 // Adjust to an even week boundary.
    109                 $w = (int)date('w',$aTime); // Day of week 0=Sun, 6=Sat
    110                 if( true ) { // Adjust to start on Mon
    111                     if( $w==0 ) $w=6;
    112                     else --$w;
    113                 }
    114                 if( $aRound == 0 ) {
    115                     $d -= $w;
    116                 }
    117                 else {
    118                     $d += (7-$w);
    119                     $h=23;$i=59;$s=59;
    120                 }
    121             }
    122         }
    123         return mktime($h,$i,$s,$m,$d,$y);
    124 
    125     }
    126 
    127     //------------------------------------------------------------------------------------------
    128     // Wrapper for AdjDate that will round a timestamp to an even date rounding
    129     // it downwards.
    130     //------------------------------------------------------------------------------------------
     75        $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
     76        $h=0;$i=0;$s=0;
     77        if( $aYearType !== false ) {
     78            $yearAdj = array(0=>1, 1=>2, 2=>5);
     79            if( $aRound == 0 ) {
     80                $y = floor($y/$yearAdj[$aYearType])*$yearAdj[$aYearType];
     81            }
     82            else {
     83                ++$y;
     84                $y = ceil($y/$yearAdj[$aYearType])*$yearAdj[$aYearType];
     85            }
     86            $m=1;$d=1;
     87        }
     88        elseif( $aMonthType !== false ) {
     89            $monthAdj = array(0=>1, 1=>6);
     90            if( $aRound == 0 ) {
     91                $m = floor($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType];
     92                $d=1;
     93            }
     94            else {
     95                ++$m;
     96                $m = ceil($m/$monthAdj[$aMonthType])*$monthAdj[$aMonthType];
     97                $d=1;
     98            }
     99        }
     100        elseif( $aDayType !== false ) {
     101            if( $aDayType == 0 ) {
     102                if( $aRound == 1 ) {
     103                    //++$d;
     104                    $h=23;$i=59;$s=59;
     105                }
     106            }
     107            else {
     108                // Adjust to an even week boundary.
     109                $w = (int)date('w',$aTime); // Day of week 0=Sun, 6=Sat
     110                if( true ) { // Adjust to start on Mon
     111                    if( $w==0 ) $w=6;
     112                    else --$w;
     113                }
     114                if( $aRound == 0 ) {
     115                    $d -= $w;
     116                }
     117                else {
     118                    $d += (7-$w);
     119                    $h=23;$i=59;$s=59;
     120                }
     121            }
     122        }
     123        return mktime($h,$i,$s,$m,$d,$y);
     124       
     125    }
     126
     127//------------------------------------------------------------------------------------------
     128// Wrapper for AdjDate that will round a timestamp to an even date rounding
     129// it downwards.
     130//------------------------------------------------------------------------------------------
    131131    function AdjStartDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) {
    132         return $this->AdjDate($aTime,0,$aYearType,$aMonthType,$aDayType);
    133     }
    134 
    135     //------------------------------------------------------------------------------------------
    136     // Wrapper for AdjDate that will round a timestamp to an even date rounding
    137     // it upwards
    138     //------------------------------------------------------------------------------------------
     132        return $this->AdjDate($aTime,0,$aYearType,$aMonthType,$aDayType);
     133    }
     134
     135//------------------------------------------------------------------------------------------
     136// Wrapper for AdjDate that will round a timestamp to an even date rounding
     137// it upwards
     138//------------------------------------------------------------------------------------------
    139139    function AdjEndDate($aTime,$aYearType=false,$aMonthType=false,$aDayType=false) {
    140         return $this->AdjDate($aTime,1,$aYearType,$aMonthType,$aDayType);
    141     }
    142 
    143     //------------------------------------------------------------------------------------------
    144     // Utility Function AdjTime()
    145     // Description: Will round a given time stamp to an even time according to
    146     // argument.
    147     //------------------------------------------------------------------------------------------
     140        return $this->AdjDate($aTime,1,$aYearType,$aMonthType,$aDayType);
     141    }
     142
     143//------------------------------------------------------------------------------------------
     144// Utility Function AdjTime()
     145// Description: Will round a given time stamp to an even time according to
     146// argument.
     147//------------------------------------------------------------------------------------------
    148148
    149149    function AdjTime($aTime,$aRound=0,$aHourType=false,$aMinType=false,$aSecType=false) {
    150         $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
    151         $h = (int)date('H',$aTime); $i = (int)date('i',$aTime); $s = (int)date('s',$aTime);
    152         if( $aHourType !== false ) {
    153             $aHourType %= 6;
    154             $hourAdj = array(0=>1, 1=>2, 2=>3, 3=>4, 4=>6, 5=>12);
    155             if( $aRound == 0 )
    156             $h = floor($h/$hourAdj[$aHourType])*$hourAdj[$aHourType];
    157             else {
    158                 if( ($h % $hourAdj[$aHourType]==0) && ($i > 0 || $s > 0) ) {
    159                     $h++;
    160                 }
    161                 $h = ceil($h/$hourAdj[$aHourType])*$hourAdj[$aHourType];
    162                 if( $h >= 24 ) {
    163                     $aTime += 86400;
    164                     $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
    165                     $h -= 24;
    166                 }
    167             }
    168             $i=0;$s=0;
    169         }
    170         elseif( $aMinType !== false ) {
    171             $aMinType %= 5;
    172             $minAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30);
    173             if( $aRound == 0 ) {
    174                 $i = floor($i/$minAdj[$aMinType])*$minAdj[$aMinType];
    175             }
    176             else {
    177                 if( ($i % $minAdj[$aMinType]==0) && $s > 0 ) {
    178                     $i++;
    179                 }
    180                 $i = ceil($i/$minAdj[$aMinType])*$minAdj[$aMinType];
    181                 if( $i >= 60) {
    182                     $aTime += 3600;
    183                     $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
    184                     $h = (int)date('H',$aTime); $i = 0;
    185                 }
    186             }
    187             $s=0;
    188         }
    189         elseif( $aSecType !== false ) {
    190             $aSecType %= 5;
    191             $secAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30);
    192             if( $aRound == 0 ) {
    193                 $s = floor($s/$secAdj[$aSecType])*$secAdj[$aSecType];
    194             }
    195             else {
    196                 $s = ceil($s/$secAdj[$aSecType]*1.0)*$secAdj[$aSecType];
    197                 if( $s >= 60) {
    198                     $s=0;
    199                     $aTime += 60;
    200                     $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
    201                     $h = (int)date('H',$aTime); $i = (int)date('i',$aTime);
    202                 }
    203             }
    204         }
    205         return mktime($h,$i,$s,$m,$d,$y);
    206     }
    207 
    208     //------------------------------------------------------------------------------------------
    209     // Wrapper for AdjTime that will round a timestamp to an even time rounding
    210     // it downwards.
    211     // Example: AdjStartTime(mktime(18,27,13,2,22,2005),false,2) => 18:20
    212     //------------------------------------------------------------------------------------------
     150        $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
     151        $h = (int)date('H',$aTime); $i = (int)date('i',$aTime); $s = (int)date('s',$aTime);
     152        if( $aHourType !== false ) {
     153            $aHourType %= 6;
     154            $hourAdj = array(0=>1, 1=>2, 2=>3, 3=>4, 4=>6, 5=>12);
     155            if( $aRound == 0 )
     156                $h = floor($h/$hourAdj[$aHourType])*$hourAdj[$aHourType];
     157            else {
     158                if( ($h % $hourAdj[$aHourType]==0) && ($i > 0 || $s > 0) ) {
     159                    $h++;
     160                }
     161                $h = ceil($h/$hourAdj[$aHourType])*$hourAdj[$aHourType];
     162                if( $h >= 24 ) {
     163                    $aTime += 86400;
     164                    $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
     165                    $h -= 24;
     166                }
     167            }
     168            $i=0;$s=0;
     169        }
     170        elseif( $aMinType !== false ) {
     171            $aMinType %= 5;
     172            $minAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30);
     173            if( $aRound == 0 ) {
     174                $i = floor($i/$minAdj[$aMinType])*$minAdj[$aMinType];
     175            }
     176            else {
     177                if( ($i % $minAdj[$aMinType]==0) && $s > 0 ) {
     178                    $i++;
     179                }
     180                $i = ceil($i/$minAdj[$aMinType])*$minAdj[$aMinType];
     181                if( $i >= 60) {
     182                    $aTime += 3600;
     183                    $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
     184                    $h = (int)date('H',$aTime); $i = 0;
     185                }
     186            }
     187            $s=0;
     188        }
     189        elseif( $aSecType !== false ) {
     190            $aSecType %= 5;
     191            $secAdj = array(0=>1, 1=>5, 2=>10, 3=>15, 4=>30);
     192            if( $aRound == 0 ) {
     193                $s = floor($s/$secAdj[$aSecType])*$secAdj[$aSecType];
     194            }
     195            else {
     196                $s = ceil($s/$secAdj[$aSecType]*1.0)*$secAdj[$aSecType];
     197                if( $s >= 60) {
     198                    $s=0;
     199                    $aTime += 60;
     200                    $y = (int)date('Y',$aTime); $m = (int)date('m',$aTime); $d = (int)date('d',$aTime);
     201                    $h = (int)date('H',$aTime); $i = (int)date('i',$aTime);
     202                }
     203            }
     204        }
     205        return mktime($h,$i,$s,$m,$d,$y);
     206    }
     207
     208//------------------------------------------------------------------------------------------
     209// Wrapper for AdjTime that will round a timestamp to an even time rounding
     210// it downwards.
     211// Example: AdjStartTime(mktime(18,27,13,2,22,2005),false,2) => 18:20
     212//------------------------------------------------------------------------------------------
    213213    function AdjStartTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) {
    214         return $this->AdjTime($aTime,0,$aHourType,$aMinType,$aSecType);
    215     }
    216 
    217     //------------------------------------------------------------------------------------------
    218     // Wrapper for AdjTime that will round a timestamp to an even time rounding
    219     // it upwards
    220     // Example: AdjEndTime(mktime(18,27,13,2,22,2005),false,2) => 18:30
    221     //------------------------------------------------------------------------------------------
     214        return $this->AdjTime($aTime,0,$aHourType,$aMinType,$aSecType);
     215    }
     216
     217//------------------------------------------------------------------------------------------
     218// Wrapper for AdjTime that will round a timestamp to an even time rounding
     219// it upwards
     220// Example: AdjEndTime(mktime(18,27,13,2,22,2005),false,2) => 18:30
     221//------------------------------------------------------------------------------------------
    222222    function AdjEndTime($aTime,$aHourType=false,$aMinType=false,$aSecType=false) {
    223         return $this->AdjTime($aTime,1,$aHourType,$aMinType,$aSecType);
    224     }
    225 
    226     //------------------------------------------------------------------------------------------
    227     // DateAutoScale
    228     // Autoscale a date axis given start and end time
    229     // Returns an array ($start,$end,$major,$minor,$format)
    230     //------------------------------------------------------------------------------------------
     223        return $this->AdjTime($aTime,1,$aHourType,$aMinType,$aSecType);
     224    }
     225
     226//------------------------------------------------------------------------------------------
     227// DateAutoScale
     228// Autoscale a date axis given start and end time
     229// Returns an array ($start,$end,$major,$minor,$format)
     230//------------------------------------------------------------------------------------------
    231231    function DoDateAutoScale($aStartTime,$aEndTime,$aDensity=0,$aAdjust=true) {
    232         // Format of array
    233         // array ( Decision point,  array( array( Major-scale-step-array ),
    234         //       array( Minor-scale-step-array ),
    235         //       array( 0=date-adjust, 1=time-adjust, adjustment-alignment) )
    236         //
    237         $scalePoints =
    238         array(
    239         /* Intervall larger than 10 years */
    240         SECPERYEAR*10,array(array(SECPERYEAR*5,SECPERYEAR*2),
    241         array(SECPERYEAR),
    242         array(0,YEARADJ_1, 0,YEARADJ_1) ),
    243 
    244         /* Intervall larger than 2 years */
    245         SECPERYEAR*2,array(array(SECPERYEAR),array(SECPERYEAR),
    246         array(0,YEARADJ_1) ),
    247 
    248         /* Intervall larger than 90 days (approx 3 month) */
    249         SECPERDAY*90,array(array(SECPERDAY*30,SECPERDAY*14,SECPERDAY*7,SECPERDAY),
    250         array(SECPERDAY*5,SECPERDAY*7,SECPERDAY,SECPERDAY),
    251         array(0,MONTHADJ_1, 0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1)),
    252 
    253         /* Intervall larger than 30 days (approx 1 month) */
    254         SECPERDAY*30,array(array(SECPERDAY*14,SECPERDAY*7,SECPERDAY*2, SECPERDAY),
    255         array(SECPERDAY,SECPERDAY,SECPERDAY,SECPERDAY),
    256         array(0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1, 0,DAYADJ_1)),
    257 
    258         /* Intervall larger than 7 days */
    259         SECPERDAY*7,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2),
    260         array(SECPERHOUR*6,SECPERHOUR*3,SECPERHOUR,SECPERHOUR),
    261         array(0,DAYADJ_1, 1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1)),
    262 
    263         /* Intervall larger than 1 day */
    264         SECPERDAY,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR),
    265         array(SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR,SECPERHOUR,SECPERHOUR),
    266         array(1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1, 1,HOURADJ_1)),
    267 
    268         /* Intervall larger than 12 hours */
    269         SECPERHOUR*12,array(array(SECPERHOUR*2,SECPERHOUR,SECPERMIN*30,900,600),
    270         array(1800,1800,900,300,300),
    271         array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ),
    272 
    273         /* Intervall larger than 2 hours */
    274         SECPERHOUR*2,array(array(SECPERHOUR,SECPERMIN*30,900,600,300),
    275         array(1800,900,300,120,60),
    276         array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ),
    277 
    278         /* Intervall larger than 1 hours */
    279         SECPERHOUR,array(array(SECPERMIN*30,900,600,300),array(900,300,120,60),
    280         array(1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ),
    281 
    282         /* Intervall larger than 30 min */
    283         SECPERMIN*30,array(array(SECPERMIN*15,SECPERMIN*10,SECPERMIN*5,SECPERMIN),
    284         array(300,300,60,10),
    285         array(1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5, 1,MINADJ_1)),
    286 
    287         /* Intervall larger than 1 min */
    288         SECPERMIN,array(array(SECPERMIN,15,10,5),
    289         array(15,5,2,1),
    290         array(1,MINADJ_1, 1,SECADJ_15, 1,SECADJ_10, 1,SECADJ_5)),
    291 
    292         /* Intervall larger than 10 sec */
    293         10,array(array(5,2),
    294         array(1,1),
    295         array(1,SECADJ_5, 1,SECADJ_1)),
    296 
    297         /* Intervall larger than 1 sec */
    298         1,array(array(1),
    299         array(1),
    300         array(1,SECADJ_1)),
    301         );
    302 
    303         $ns = count($scalePoints);
    304         // Establish major and minor scale units for the date scale
    305         $diff = $aEndTime - $aStartTime;
    306         if( $diff < 1 ) return false;
    307         $done=false;
    308         $i=0;
    309         while( ! $done ) {
    310             if( $diff > $scalePoints[2*$i] ) {
    311                 // Get major and minor scale for this intervall
    312                 $scaleSteps = $scalePoints[2*$i+1];
    313                 $major = $scaleSteps[0][min($aDensity,count($scaleSteps[0])-1)];
    314                 // Try to find out which minor step looks best
    315                 $minor = $scaleSteps[1][min($aDensity,count($scaleSteps[1])-1)];
    316                 if( $aAdjust ) {
    317                     // Find out how we should align the start and end timestamps
    318                     $idx = 2*min($aDensity,floor(count($scaleSteps[2])/2)-1);
    319                     if( $scaleSteps[2][$idx] === 0 ) {
    320                         // Use date adjustment
    321                         $adj = $scaleSteps[2][$idx+1];
    322                         if( $adj >= 30 ) {
    323                             $start = $this->AdjStartDate($aStartTime,$adj-30);
    324                             $end   = $this->AdjEndDate($aEndTime,$adj-30);
    325                         }
    326                         elseif( $adj >= 20 ) {
    327                             $start = $this->AdjStartDate($aStartTime,false,$adj-20);
    328                             $end   = $this->AdjEndDate($aEndTime,false,$adj-20);
    329                         }
    330                         else {
    331                             $start = $this->AdjStartDate($aStartTime,false,false,$adj);
    332                             $end   = $this->AdjEndDate($aEndTime,false,false,$adj);
    333                             // We add 1 second for date adjustment to make sure we end on 00:00 the following day
    334                             // This makes the final major tick be srawn when we step day-by-day instead of ending
    335                             // on xx:59:59 which would not draw the final major tick
    336                             $end++;
    337                         }
    338                     }
    339                     else {
    340                         // Use time adjustment
    341                         $adj = $scaleSteps[2][$idx+1];
    342                         if( $adj >= 30 ) {
    343                             $start = $this->AdjStartTime($aStartTime,$adj-30);
    344                             $end   = $this->AdjEndTime($aEndTime,$adj-30);
    345                         }
    346                         elseif( $adj >= 20 ) {
    347                             $start = $this->AdjStartTime($aStartTime,false,$adj-20);
    348                             $end   = $this->AdjEndTime($aEndTime,false,$adj-20);
    349                         }
    350                         else {
    351                             $start = $this->AdjStartTime($aStartTime,false,false,$adj);
    352                             $end   = $this->AdjEndTime($aEndTime,false,false,$adj);
    353                         }
    354                     }
    355                 }
    356                 // If the overall date span is larger than 1 day ten we show date
    357                 $format = '';
    358                 if( ($end-$start) > SECPERDAY ) {
    359                     $format = 'Y-m-d ';
    360                 }
    361                 // If the major step is less than 1 day we need to whow hours + min
    362                 if( $major < SECPERDAY ) {
    363                     $format .= 'H:i';
    364                 }
    365                 // If the major step is less than 1 min we need to show sec
    366                 if( $major < 60 ) {
    367                     $format .= ':s';
    368                 }
    369                 $done=true;
    370             }
    371             ++$i;
    372         }
    373         return array($start,$end,$major,$minor,$format);
     232        // Format of array
     233        // array ( Decision point,  array( array( Major-scale-step-array ), 
     234        //                          array( Minor-scale-step-array ),
     235        //                          array( 0=date-adjust, 1=time-adjust, adjustment-alignment) )
     236        //
     237        $scalePoints =
     238            array(
     239                /* Intervall larger than 10 years */
     240                SECPERYEAR*10,array(array(SECPERYEAR*5,SECPERYEAR*2),
     241                                    array(SECPERYEAR),
     242                                    array(0,YEARADJ_1, 0,YEARADJ_1) ),
     243
     244                /* Intervall larger than 2 years */
     245                SECPERYEAR*2,array(array(SECPERYEAR),array(SECPERYEAR),
     246                                   array(0,YEARADJ_1) ),
     247
     248                /* Intervall larger than 90 days (approx 3 month) */
     249                SECPERDAY*90,array(array(SECPERDAY*30,SECPERDAY*14,SECPERDAY*7,SECPERDAY),
     250                                   array(SECPERDAY*5,SECPERDAY*7,SECPERDAY,SECPERDAY),
     251                                   array(0,MONTHADJ_1, 0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1)),
     252
     253                /* Intervall larger than 30 days (approx 1 month) */
     254                SECPERDAY*30,array(array(SECPERDAY*14,SECPERDAY*7,SECPERDAY*2, SECPERDAY),
     255                                   array(SECPERDAY,SECPERDAY,SECPERDAY,SECPERDAY),
     256                                   array(0,DAYADJ_WEEK, 0,DAYADJ_1, 0,DAYADJ_1, 0,DAYADJ_1)),
     257
     258                /* Intervall larger than 7 days */
     259                SECPERDAY*7,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2),
     260                                  array(SECPERHOUR*6,SECPERHOUR*3,SECPERHOUR,SECPERHOUR),
     261                                  array(0,DAYADJ_1, 1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1)),
     262
     263                /* Intervall larger than 1 day */
     264                SECPERDAY,array(array(SECPERDAY,SECPERHOUR*12,SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR),
     265                                array(SECPERHOUR*6,SECPERHOUR*2,SECPERHOUR,SECPERHOUR,SECPERHOUR),
     266                                array(1,HOURADJ_12, 1,HOURADJ_6, 1,HOURADJ_1, 1,HOURADJ_1)),
     267
     268                /* Intervall larger than 12 hours */
     269                SECPERHOUR*12,array(array(SECPERHOUR*2,SECPERHOUR,SECPERMIN*30,900,600),
     270                                    array(1800,1800,900,300,300),
     271                                    array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ),
     272
     273                /* Intervall larger than 2 hours */
     274                SECPERHOUR*2,array(array(SECPERHOUR,SECPERMIN*30,900,600,300),
     275                                   array(1800,900,300,120,60),
     276                                   array(1,HOURADJ_1, 1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ),
     277
     278                /* Intervall larger than 1 hours */
     279                SECPERHOUR,array(array(SECPERMIN*30,900,600,300),array(900,300,120,60),
     280                                array(1,MINADJ_30, 1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5) ),
     281
     282                /* Intervall larger than 30 min */
     283                SECPERMIN*30,array(array(SECPERMIN*15,SECPERMIN*10,SECPERMIN*5,SECPERMIN),
     284                                   array(300,300,60,10),
     285                                   array(1,MINADJ_15, 1,MINADJ_10, 1,MINADJ_5, 1,MINADJ_1)),
     286
     287                /* Intervall larger than 1 min */
     288                SECPERMIN,array(array(SECPERMIN,15,10,5),
     289                                array(15,5,2,1),
     290                                array(1,MINADJ_1, 1,SECADJ_15, 1,SECADJ_10, 1,SECADJ_5)),
     291
     292                /* Intervall larger than 10 sec */
     293                10,array(array(5,2),
     294                        array(1,1),
     295                        array(1,SECADJ_5, 1,SECADJ_1)),
     296
     297                /* Intervall larger than 1 sec */
     298                1,array(array(1),
     299                        array(1),
     300                        array(1,SECADJ_1)),
     301                );
     302
     303        $ns = count($scalePoints);
     304        // Establish major and minor scale units for the date scale
     305        $diff = $aEndTime - $aStartTime;
     306        if( $diff < 1 ) return false;
     307        $done=false;
     308        $i=0;
     309        while( ! $done ) {
     310            if( $diff > $scalePoints[2*$i] ) {
     311                // Get major and minor scale for this intervall
     312                $scaleSteps = $scalePoints[2*$i+1];
     313                $major = $scaleSteps[0][min($aDensity,count($scaleSteps[0])-1)];
     314                // Try to find out which minor step looks best
     315                $minor = $scaleSteps[1][min($aDensity,count($scaleSteps[1])-1)];
     316                if( $aAdjust ) {
     317                    // Find out how we should align the start and end timestamps
     318                    $idx = 2*min($aDensity,floor(count($scaleSteps[2])/2)-1);
     319                    if( $scaleSteps[2][$idx] === 0 ) {
     320                        // Use date adjustment
     321                        $adj = $scaleSteps[2][$idx+1];
     322                        if( $adj >= 30 ) {
     323                            $start = $this->AdjStartDate($aStartTime,$adj-30);
     324                            $end   = $this->AdjEndDate($aEndTime,$adj-30);
     325                        }
     326                        elseif( $adj >= 20 ) {
     327                            $start = $this->AdjStartDate($aStartTime,false,$adj-20);
     328                            $end   = $this->AdjEndDate($aEndTime,false,$adj-20);
     329                        }
     330                        else {
     331                            $start = $this->AdjStartDate($aStartTime,false,false,$adj);
     332                            $end   = $this->AdjEndDate($aEndTime,false,false,$adj);
     333                            // We add 1 second for date adjustment to make sure we end on 00:00 the following day
     334                            // This makes the final major tick be srawn when we step day-by-day instead of ending
     335                            // on xx:59:59 which would not draw the final major tick
     336                            $end++;     
     337                        }
     338                    }
     339                    else {
     340                        // Use time adjustment
     341                        $adj = $scaleSteps[2][$idx+1];
     342                        if( $adj >= 30 ) {
     343                            $start = $this->AdjStartTime($aStartTime,$adj-30);
     344                            $end   = $this->AdjEndTime($aEndTime,$adj-30);
     345                        }
     346                        elseif( $adj >= 20 ) {
     347                            $start = $this->AdjStartTime($aStartTime,false,$adj-20);
     348                            $end   = $this->AdjEndTime($aEndTime,false,$adj-20);
     349                        }
     350                        else {
     351                            $start = $this->AdjStartTime($aStartTime,false,false,$adj);
     352                            $end   = $this->AdjEndTime($aEndTime,false,false,$adj);                 
     353                        }
     354                    }
     355                }
     356                // If the overall date span is larger than 1 day ten we show date
     357                $format = '';
     358                if( ($end-$start) > SECPERDAY ) {
     359                    $format = 'Y-m-d ';
     360                }
     361                // If the major step is less than 1 day we need to whow hours + min
     362                if( $major < SECPERDAY ) {
     363                    $format .= 'H:i';
     364                }
     365                // If the major step is less than 1 min we need to show sec
     366                if( $major < 60 ) {
     367                    $format .= ':s';
     368                }
     369                $done=true;
     370            }
     371            ++$i;
     372        }
     373        return array($start,$end,$major,$minor,$format);
    374374    }
    375375
    376376    // Overrides the automatic determined date format. Must be a valid date() format string
    377377    function SetDateFormat($aFormat) {
    378         $this->date_format = $aFormat;
    379         $this->ticks->SetLabelDateFormat($this->date_format);
     378        $this->date_format = $aFormat;
     379        $this->ticks->SetLabelDateFormat($this->date_format);
    380380    }
    381381
    382382    function AdjustForDST($aFlg=true) {
    383         $this->ticks->AdjustForDST($aFlg);
     383        $this->ticks->AdjustForDST($aFlg);
    384384    }
    385385
    386386
    387387    function SetDateAlign($aStartAlign,$aEndAlign=false) {
    388         if( $aEndAlign === false ) {
    389             $aEndAlign=$aStartAlign;
    390         }
    391         $this->iStartAlign = $aStartAlign;
    392         $this->iEndAlign = $aEndAlign;
     388        if( $aEndAlign === false ) {
     389            $aEndAlign=$aStartAlign;
     390        }
     391        $this->iStartAlign = $aStartAlign;
     392        $this->iEndAlign = $aEndAlign;
    393393    }
    394394
    395395    function SetTimeAlign($aStartAlign,$aEndAlign=false) {
    396         if( $aEndAlign === false ) {
    397             $aEndAlign=$aStartAlign;
    398         }
    399         $this->iStartTimeAlign = $aStartAlign;
    400         $this->iEndTimeAlign = $aEndAlign;
     396        if( $aEndAlign === false ) {
     397            $aEndAlign=$aStartAlign;
     398        }
     399        $this->iStartTimeAlign = $aStartAlign;
     400        $this->iEndTimeAlign = $aEndAlign;
    401401    }
    402402
    403403
    404404    function AutoScale($img,$aStartTime,$aEndTime,$aNumSteps,$_adummy=false) {
    405         // We need to have one dummy argument to make the signature of AutoScale()
    406         // identical to LinearScale::AutoScale
    407         if( $aStartTime == $aEndTime ) {
    408             // Special case when we only have one data point.
    409             // Create a small artifical intervall to do the autoscaling
    410             $aStartTime -= 10;
    411             $aEndTime += 10;
    412         }
    413         $done=false;
    414         $i=0;
    415         while( ! $done && $i < 5) {
    416             list($adjstart,$adjend,$maj,$min,$format) = $this->DoDateAutoScale($aStartTime,$aEndTime,$i);
    417             $n = floor(($adjend-$adjstart)/$maj);
    418             if( $n * 1.7 > $aNumSteps ) {
    419                 $done=true;
    420             }
    421             $i++;
    422         }
    423 
    424         /*
    425          if( 0 ) { // DEBUG
    426          echo "    Start =".date("Y-m-d H:i:s",$aStartTime)."<br>";
    427          echo "    End   =".date("Y-m-d H:i:s",$aEndTime)."<br>";
    428          echo "Adj Start =".date("Y-m-d H:i:s",$adjstart)."<br>";
    429          echo "Adj End   =".date("Y-m-d H:i:s",$adjend)."<p>";
    430          echo "Major = $maj s, ".floor($maj/60)."min, ".floor($maj/3600)."h, ".floor($maj/86400)."day<br>";
    431          echo "Min = $min s, ".floor($min/60)."min, ".floor($min/3600)."h, ".floor($min/86400)."day<br>";
    432          echo "Format=$format<p>";
    433          }
    434          */
    435 
    436         if( $this->iStartTimeAlign !== false && $this->iStartAlign !== false ) {
    437             JpGraphError::RaiseL(3001);
    438             //('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both');
    439         }
    440 
    441         if( $this->iStartTimeAlign !== false ) {
    442             if( $this->iStartTimeAlign >= 30 ) {
    443                 $adjstart = $this->AdjStartTime($aStartTime,$this->iStartTimeAlign-30);
    444             }
    445             elseif(  $this->iStartTimeAlign >= 20 ) {
    446                 $adjstart = $this->AdjStartTime($aStartTime,false,$this->iStartTimeAlign-20);
    447             }
    448             else {
    449                 $adjstart = $this->AdjStartTime($aStartTime,false,false,$this->iStartTimeAlign);
    450             }
    451         }
    452         if( $this->iEndTimeAlign !== false ) {
    453             if( $this->iEndTimeAlign >= 30 ) {
    454                 $adjend = $this->AdjEndTime($aEndTime,$this->iEndTimeAlign-30);
    455             }
    456             elseif(  $this->iEndTimeAlign >= 20 ) {
    457                 $adjend = $this->AdjEndTime($aEndTime,false,$this->iEndTimeAlign-20);
    458             }
    459             else {
    460                 $adjend = $this->AdjEndTime($aEndTime,false,false,$this->iEndTimeAlign);
    461             }
    462         }
    463 
    464 
    465 
    466         if( $this->iStartAlign !== false ) {
    467             if( $this->iStartAlign >= 30 ) {
    468                 $adjstart = $this->AdjStartDate($aStartTime,$this->iStartAlign-30);
    469             }
    470             elseif(  $this->iStartAlign >= 20 ) {
    471                 $adjstart = $this->AdjStartDate($aStartTime,false,$this->iStartAlign-20);
    472             }
    473             else {
    474                 $adjstart = $this->AdjStartDate($aStartTime,false,false,$this->iStartAlign);
    475             }
    476         }
    477         if( $this->iEndAlign !== false ) {
    478             if( $this->iEndAlign >= 30 ) {
    479                 $adjend = $this->AdjEndDate($aEndTime,$this->iEndAlign-30);
    480             }
    481             elseif(  $this->iEndAlign >= 20 ) {
    482                 $adjend = $this->AdjEndDate($aEndTime,false,$this->iEndAlign-20);
    483             }
    484             else {
    485                 $adjend = $this->AdjEndDate($aEndTime,false,false,$this->iEndAlign);
    486             }
    487         }
    488         $this->Update($img,$adjstart,$adjend);
    489         if( ! $this->ticks->IsSpecified() )
    490         $this->ticks->Set($maj,$min);
    491         if( $this->date_format == '' )
    492         $this->ticks->SetLabelDateFormat($format);
    493         else
    494         $this->ticks->SetLabelDateFormat($this->date_format);
     405        // We need to have one dummy argument to make the signature of AutoScale()
     406        // identical to LinearScale::AutoScale
     407        if( $aStartTime == $aEndTime ) {
     408            // Special case when we only have one data point.
     409            // Create a small artifical intervall to do the autoscaling
     410            $aStartTime -= 10;
     411            $aEndTime += 10;
     412        }
     413        $done=false;
     414        $i=0;
     415        while( ! $done && $i < 5) {
     416            list($adjstart,$adjend,$maj,$min,$format) = $this->DoDateAutoScale($aStartTime,$aEndTime,$i);
     417            $n = floor(($adjend-$adjstart)/$maj);
     418            if( $n * 1.7 > $aNumSteps ) {
     419                $done=true;
     420            }
     421            $i++;
     422        }
     423       
     424        /*
     425        if( 0 ) { // DEBUG
     426            echo "    Start =".date("Y-m-d H:i:s",$aStartTime)."<br>";
     427            echo "    End   =".date("Y-m-d H:i:s",$aEndTime)."<br>";
     428            echo "Adj Start =".date("Y-m-d H:i:s",$adjstart)."<br>";
     429            echo "Adj End   =".date("Y-m-d H:i:s",$adjend)."<p>";
     430            echo "Major = $maj s, ".floor($maj/60)."min, ".floor($maj/3600)."h, ".floor($maj/86400)."day<br>";
     431            echo "Min = $min s, ".floor($min/60)."min, ".floor($min/3600)."h, ".floor($min/86400)."day<br>";
     432            echo "Format=$format<p>";
     433        }
     434        */
     435       
     436        if( $this->iStartTimeAlign !== false && $this->iStartAlign !== false ) {
     437            JpGraphError::RaiseL(3001);
     438//('It is only possible to use either SetDateAlign() or SetTimeAlign() but not both');
     439        }
     440
     441        if( $this->iStartTimeAlign !== false ) {
     442            if( $this->iStartTimeAlign >= 30 ) {
     443                $adjstart = $this->AdjStartTime($aStartTime,$this->iStartTimeAlign-30);
     444            }
     445            elseif(  $this->iStartTimeAlign >= 20 ) {
     446                $adjstart = $this->AdjStartTime($aStartTime,false,$this->iStartTimeAlign-20);
     447            }
     448            else {
     449                $adjstart = $this->AdjStartTime($aStartTime,false,false,$this->iStartTimeAlign);
     450            }
     451        }
     452        if( $this->iEndTimeAlign !== false ) {
     453            if( $this->iEndTimeAlign >= 30 ) {
     454                $adjend = $this->AdjEndTime($aEndTime,$this->iEndTimeAlign-30);
     455            }
     456            elseif(  $this->iEndTimeAlign >= 20 ) {
     457                $adjend = $this->AdjEndTime($aEndTime,false,$this->iEndTimeAlign-20);
     458            }
     459            else {
     460                $adjend = $this->AdjEndTime($aEndTime,false,false,$this->iEndTimeAlign);
     461            }
     462        }
     463
     464
     465       
     466        if( $this->iStartAlign !== false ) {
     467            if( $this->iStartAlign >= 30 ) {
     468                $adjstart = $this->AdjStartDate($aStartTime,$this->iStartAlign-30);
     469            }
     470            elseif(  $this->iStartAlign >= 20 ) {
     471                $adjstart = $this->AdjStartDate($aStartTime,false,$this->iStartAlign-20);
     472            }
     473            else {
     474                $adjstart = $this->AdjStartDate($aStartTime,false,false,$this->iStartAlign);
     475            }
     476        }
     477        if( $this->iEndAlign !== false ) {
     478            if( $this->iEndAlign >= 30 ) {
     479                $adjend = $this->AdjEndDate($aEndTime,$this->iEndAlign-30);
     480            }
     481            elseif(  $this->iEndAlign >= 20 ) {
     482                $adjend = $this->AdjEndDate($aEndTime,false,$this->iEndAlign-20);
     483            }
     484            else {
     485                $adjend = $this->AdjEndDate($aEndTime,false,false,$this->iEndAlign);
     486            }
     487        }
     488        $this->Update($img,$adjstart,$adjend);
     489        if( ! $this->ticks->IsSpecified() )
     490            $this->ticks->Set($maj,$min);
     491        if( $this->date_format == '' )
     492            $this->ticks->SetLabelDateFormat($format);
     493        else
     494            $this->ticks->SetLabelDateFormat($this->date_format);
    495495    }
    496496}
  • trunk/client/modules/Elezioni/grafici/jpgraph_errhandler.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_ERRHANDLER.PHP
    4 // Description: Error handler class together with handling of localized
    5 //              error messages. All localized error messages are stored
    6 //              in a separate file under the "lang/" subdirectory.
    7 // Created:     2006-09-24
    8 // Ver:         $Id: jpgraph_errhandler.inc.php 1920 2009-12-08 10:02:26Z ljp $
     3// File:        JPGRAPH_ERRHANDLER.PHP
     4// Description: Error handler class together with handling of localized
     5//              error messages. All localized error messages are stored
     6//              in a separate file under the "lang/" subdirectory.
     7// Created:     2006-09-24
     8// Ver:         $Id: jpgraph_errhandler.inc.php 973 2008-03-09 15:29:44Z ljp $
    99//
    1010// Copyright 2006 (c) Aditus Consulting. All rights reserved.
    1111//========================================================================
    1212
    13 if( !defined('DEFAULT_ERR_LOCALE') ) {
    14     define('DEFAULT_ERR_LOCALE','en');
    15 }
    16 
    17 if( !defined('USE_IMAGE_ERROR_HANDLER') ) {
    18     define('USE_IMAGE_ERROR_HANDLER',true);
    19 }
    2013
    2114GLOBAL $__jpg_err_locale ;
     
    2417class ErrMsgText {
    2518    private $lt=NULL;
    26     function __construct() {
    27         GLOBAL $__jpg_err_locale;
    28         $file = 'lang/'.$__jpg_err_locale.'.inc.php';
    29 
    30         // If the chosen locale doesn't exist try english
    31         if( !file_exists(dirname(__FILE__).'/'.$file) ) {
    32             $__jpg_err_locale = 'en';
    33         }
    34 
    35         $file = 'lang/'.$__jpg_err_locale.'.inc.php';
    36         if( !file_exists(dirname(__FILE__).'/'.$file) ) {
    37             die('Chosen locale file ("'.$file.'") for error messages does not exist or is not readable for the PHP process. Please make sure that the file exists and that the file permissions are such that the PHP process is allowed to read this file.');
    38         }
    39         require($file);
    40         $this->lt = $_jpg_messages;
     19    function ErrMsgText() {
     20        GLOBAL $__jpg_err_locale;
     21        $file = 'lang/'.$__jpg_err_locale.'.inc.php';
     22
     23        // If the chosen locale doesn't exist try english
     24        if( !file_exists(dirname(__FILE__).'/'.$file) ) {
     25            $__jpg_err_locale = 'en';
     26        }
     27
     28        $file = 'lang/'.$__jpg_err_locale.'.inc.php';
     29        if( !file_exists(dirname(__FILE__).'/'.$file) ) {
     30            die('Chosen locale file ("'.$file.'") for error messages does not exist or is not readable for the PHP process. Please make sure that the file exists and that the file permissions are such that the PHP process is allowed to read this file.');
     31        }
     32        require($file);
     33        $this->lt = $_jpg_messages;
    4134    }
    4235
    4336    function Get($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
    44         GLOBAL $__jpg_err_locale;
    45         if( !isset($this->lt[$errnbr]) ) {
    46             return 'Internal error: The specified error message ('.$errnbr.') does not exist in the chosen locale ('.$__jpg_err_locale.')';
    47         }
    48         $ea = $this->lt[$errnbr];
    49         $j=0;
    50         if( $a1 !== null ) {
    51             $argv[$j++] = $a1;
    52             if( $a2 !== null ) {
    53                 $argv[$j++] = $a2;
    54                 if( $a3 !== null ) {
    55                     $argv[$j++] = $a3;
    56                     if( $a4 !== null ) {
    57                         $argv[$j++] = $a4;
    58                         if( $a5 !== null ) {
    59                             $argv[$j++] = $a5;
    60                         }
    61                     }
    62                 }
    63             }
    64         }
    65         $numargs = $j;
    66         if( $ea[1] != $numargs ) {
    67             // Error message argument count do not match.
    68             // Just return the error message without arguments.
    69             return $ea[0];
    70         }
    71         switch( $numargs ) {
    72             case 1:
    73                 $msg = sprintf($ea[0],$argv[0]);
    74                 break;
    75             case 2:
    76                 $msg = sprintf($ea[0],$argv[0],$argv[1]);
    77                 break;
    78             case 3:
    79                 $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2]);
    80                 break;
    81             case 4:
    82                 $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3]);
    83                 break;
    84             case 5:
    85                 $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3],$argv[4]);
    86                 break;
    87             case 0:
    88             default:
    89                 $msg = sprintf($ea[0]);
    90                 break;
    91         }
    92         return $msg;
    93     }
    94 }
    95      
     37        GLOBAL $__jpg_err_locale;
     38        if( !isset($this->lt[$errnbr]) ) {
     39            return 'Internal error: The specified error message ('.$errnbr.') does not exist in the chosen locale ('.$__jpg_err_locale.')';
     40        }
     41        $ea = $this->lt[$errnbr];
     42        $j=0;
     43        if( $a1 !== null ) {
     44            $argv[$j++] = $a1;
     45            if( $a2 !== null ) {
     46                $argv[$j++] = $a2;
     47                if( $a3 !== null ) {
     48                    $argv[$j++] = $a3;
     49                    if( $a4 !== null ) {
     50                        $argv[$j++] = $a4;
     51                        if( $a5 !== null ) {
     52                            $argv[$j++] = $a5;
     53                        }
     54                    }
     55                }
     56            }
     57        }
     58        $numargs = $j;
     59        if( $ea[1] != $numargs ) {
     60            // Error message argument count do not match.
     61            // Just return the error message without arguments.
     62            return $ea[0];
     63        }
     64        switch( $numargs ) {
     65            case 1:
     66                $msg = sprintf($ea[0],$argv[0]);
     67                break;
     68            case 2:
     69                $msg = sprintf($ea[0],$argv[0],$argv[1]);
     70                break;
     71            case 3:
     72                $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2]);
     73                break;
     74            case 4:
     75                $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3]);
     76                break;
     77            case 5:
     78                $msg = sprintf($ea[0],$argv[0],$argv[1],$argv[2],$argv[3],$argv[4]);
     79                break;
     80            case 0:
     81            default:
     82                $msg = sprintf($ea[0]);
     83                break;
     84        }
     85        return $msg;
     86    }
     87}
     88
    9689//
    9790// A wrapper class that is used to access the specified error object
     
    10093//
    10194class JpGraphError {
    102     private static $__iImgFlg = true;
    103     private static $__iLogFile = '';
    104     private static $__iTitle = 'JpGraph Error: ';
     95    private static $__jpg_err;
     96    public static function Install($aErrObject) {
     97        self::$__jpg_err = new $aErrObject;
     98    }
    10599    public static function Raise($aMsg,$aHalt=true){
    106         throw new JpGraphException($aMsg);
     100        self::$__jpg_err->Raise($aMsg,$aHalt);
    107101    }
    108102    public static function SetErrLocale($aLoc) {
    109         GLOBAL $__jpg_err_locale ;
    110         $__jpg_err_locale = $aLoc;
     103        GLOBAL $__jpg_err_locale ;
     104        $__jpg_err_locale = $aLoc;
    111105    }
    112106    public static function RaiseL($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
    113         throw new JpGraphExceptionL($errnbr,$a1,$a2,$a3,$a4,$a5);
    114     }
    115     public static function SetImageFlag($aFlg=true) {
    116         self::$__iImgFlg = $aFlg;
    117     }
    118     public static function GetImageFlag() {
    119         return self::$__iImgFlg;
    120     }
    121     public static function SetLogFile($aFile) {
    122         self::$__iLogFile = $aFile;
    123     }
    124     public static function GetLogFile() {
    125         return self::$__iLogFile;
    126     }
    127     public static function SetTitle($aTitle) {
    128         self::$__iTitle = $aTitle;
    129     }
    130     public static function GetTitle() {
    131         return self::$__iTitle;
    132     }   
    133 }
    134 
    135 class JpGraphException extends Exception {
    136     // Redefine the exception so message isn't optional
    137     public function __construct($message, $code = 0) {
    138         // make sure everything is assigned properly
    139         parent::__construct($message, $code);
    140     }
    141     // custom string representation of object
    142     public function _toString() {
    143         return __CLASS__ . ": [{$this->code}]: {$this->message} at " . basename($this->getFile()) . ":" . $this->getLine() . "\n" . $this->getTraceAsString() . "\n";
    144     }
    145     // custom representation of error as an image
    146     public function Stroke() {
    147         if( JpGraphError::GetImageFlag() ) {
    148                 $errobj = new JpGraphErrObjectImg();
    149                 $errobj->SetTitle(JpGraphError::GetTitle());
    150         }
    151         else {                 
    152                 $errobj = new JpGraphErrObject();
    153                 $errobj->SetTitle(JpGraphError::GetTitle());                   
    154                 $errobj->SetStrokeDest(JpGraphError::GetLogFile());
    155         }
    156         $errobj->Raise($this->getMessage());
    157     }
    158     static public function defaultHandler(Exception $exception) {
    159         global $__jpg_OldHandler;
    160         if( $exception instanceof JpGraphException ) {
    161             $exception->Stroke();
    162         }
    163         else {
    164             // Restore old handler
    165             if( $__jpg_OldHandler !== NULL ) {
    166                 set_exception_handler($__jpg_OldHandler);
    167             }
    168             throw $exception;
    169         }
    170     }
    171 }
    172 
    173 class JpGraphExceptionL extends JpGraphException {
    174    // Redefine the exception so message isn't optional
    175     public function __construct($errcode,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
    176         // make sure everything is assigned properly
    177         $errtxt = new ErrMsgText();
    178         JpGraphError::SetTitle('JpGraph Error: '.$errcode);
    179         parent::__construct($errtxt->Get($errcode,$a1,$a2,$a3,$a4,$a5), 0);
    180     }
    181 }
    182 
    183 // Setup the default handler
    184 global $__jpg_OldHandler;
    185 $__jpg_OldHandler = set_exception_handler(array('JpGraphException','defaultHandler'));
     107        $t = new ErrMsgText();
     108        $msg = $t->Get($errnbr,$a1,$a2,$a3,$a4,$a5);
     109        self::$__jpg_err->Raise($msg);
     110    }
     111}
    186112
    187113//
     
    194120class JpGraphErrObject {
    195121
    196     protected $iTitle = "JpGraph error: ";
     122    protected $iTitle = "JpGraph Error";
    197123    protected $iDest = false;
    198124
    199125
    200     function __construct() {
    201         // Empty. Reserved for future use
     126    function JpGraphErrObject() {
     127        // Empty. Reserved for future use
    202128    }
    203129
    204130    function SetTitle($aTitle) {
    205         $this->iTitle = $aTitle;
    206     }
    207 
    208     function SetStrokeDest($aDest) {
    209         $this->iDest = $aDest;
     131        $this->iTitle = $aTitle;
     132    }
     133
     134    function SetStrokeDest($aDest) { 
     135        $this->iDest = $aDest;
    210136    }
    211137
    212138    // If aHalt is true then execution can't continue. Typical used for fatal errors
    213     function Raise($aMsg,$aHalt=false) {
    214         if( $this->iDest != '' ) {
    215                 if( $this->iDest == 'syslog' ) {
    216                         error_log($this->iTitle.$aMsg);
    217                 }
    218                 else {
    219                         $str = '['.date('r').'] '.$this->iTitle.$aMsg."\n";
    220                         $f = @fopen($this->iDest,'a');
    221                 if( $f ) {             
    222                         @fwrite($f,$str);
    223                     @fclose($f);
    224                 }
    225                 }
    226         }
    227         else {
    228                 $aMsg = $this->iTitle.$aMsg;           
    229                 // Check SAPI and if we are called from the command line
    230                 // send the error to STDERR instead
    231                 if( PHP_SAPI == 'cli' ) {
    232                         fwrite(STDERR,$aMsg);
    233                 }
    234                 else {
    235                 echo $aMsg;
    236                 }
    237         }
    238         if( $aHalt )
    239                 exit(1);
     139    function Raise($aMsg,$aHalt=true) {
     140        $aMsg = $this->iTitle.' '.$aMsg;
     141        if ($this->iDest) {
     142            $f = @fopen($this->iDest,'a');
     143            if( $f ) {
     144                @fwrite($f,$aMsg);
     145                @fclose($f);
     146            }
     147        }
     148        else {
     149            echo $aMsg;
     150        }
     151        if( $aHalt )
     152            die();
    240153    }
    241154}
     
    245158//==============================================================
    246159class JpGraphErrObjectImg extends JpGraphErrObject {
    247    
    248     function __construct() {
    249         parent::__construct();
    250         // Empty. Reserved for future use
    251     }
    252160
    253161    function Raise($aMsg,$aHalt=true) {
    254         $img_iconerror =
    255      'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaV'.
    256      'BMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'.
    257      'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpY'.
    258      'iYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'.
    259      'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
    260      'IAAAsSAdLdfvwAAAAHdElNRQfTBgISOCqusfs5AAABLUlEQVR4'.
    261      '2tWV3XKCMBBGWfkranCIVClKLd/7P2Q3QsgCxjDTq+6FE2cPH+'.
    262      'xJ0Ogn2lQbsT+Wrs+buAZAV4W5T6Bs0YXBBwpKgEuIu+JERAX6'.
    263      'wM2rHjmDdEITmsQEEmWADgZm6rAjhXsoMGY9B/NZBwJzBvn+e3'.
    264      'wHntCAJdGu9SviwIwoZVDxPB9+Rc0TSEbQr0j3SA1gwdSn6Db0'.
    265      '6Tm1KfV6yzWGQO7zdpvyKLKBDmRFjzeB3LYgK7r6A/noDAfjtS'.
    266      'IXaIzbJSv6WgUebTMV4EoRB8a2mQiQjgtF91HdKDKZ1gtFtQjk'.
    267      'YcWaR5OKOhkYt+ZsTFdJRfPAApOpQYJTNHvCRSJR6SJngQadfc'.
    268      'vd69OLMddVOPCGVnmrFD8bVYd3JXfxXPtLR/+mtv59/ALWiiMx'.
    269      'qL72fwAAAABJRU5ErkJggg==' ;
    270 
    271        
    272         if( function_exists("imagetypes") ) {
    273             $supported = imagetypes();
    274         } else {
    275             $supported = 0;
    276         }
    277 
    278         if( !function_exists('imagecreatefromstring') ) {
    279             $supported = 0;
    280         }
    281        
    282         if( ob_get_length() || headers_sent() || !($supported & IMG_PNG) ) {
    283             // Special case for headers already sent or that the installation doesn't support
    284             // the PNG format (which the error icon is encoded in).
    285             // Dont return an image since it can't be displayed
    286             die($this->iTitle.' '.$aMsg);
    287         }
    288 
    289         $aMsg = wordwrap($aMsg,55);
    290         $lines = substr_count($aMsg,"\n");
    291 
    292         // Create the error icon GD
    293         $erricon = Image::CreateFromString(base64_decode($img_iconerror));
    294 
    295         // Create an image that contains the error text.
    296         $w=400;
    297         $h=100 + 15*max(0,$lines-3);
    298 
    299         $img = new Image($w,$h);
    300 
    301 
    302         // Drop shadow
    303         $img->SetColor("gray");
    304         $img->FilledRectangle(5,5,$w-1,$h-1,10);
    305         $img->SetColor("gray:0.7");
    306         $img->FilledRectangle(5,5,$w-3,$h-3,10);
    307 
    308         // Window background
    309         $img->SetColor("lightblue");
    310         $img->FilledRectangle(1,1,$w-5,$h-5);
    311         $img->CopyCanvasH($img->img,$erricon,5,30,0,0,40,40);
    312 
    313         // Window border
    314         $img->SetColor("black");
    315         $img->Rectangle(1,1,$w-5,$h-5);
    316         $img->Rectangle(0,0,$w-4,$h-4);
    317 
    318         // Window top row
    319         $img->SetColor("darkred");
    320         for($y=3; $y < 18; $y += 2 )
    321         $img->Line(1,$y,$w-6,$y);
    322 
    323         // "White shadow"
    324         $img->SetColor("white");
    325 
    326         // Left window edge
    327         $img->Line(2,2,2,$h-5);
    328         $img->Line(2,2,$w-6,2);
    329 
    330         // "Gray button shadow"
    331         $img->SetColor("darkgray");
    332 
    333         // Gray window shadow
    334         $img->Line(2,$h-6,$w-5,$h-6);
    335         $img->Line(3,$h-7,$w-5,$h-7);
    336 
    337         // Window title
    338         $m = floor($w/2-5);
    339         $l = 110;
    340         $img->SetColor("lightgray:1.3");
    341         $img->FilledRectangle($m-$l,2,$m+$l,16);
    342 
    343         // Stroke text
    344         $img->SetColor("darkred");
    345         $img->SetFont(FF_FONT2,FS_BOLD);
    346         $img->StrokeText($m-90,15,$this->iTitle);
    347         $img->SetColor("black");
    348         $img->SetFont(FF_FONT1,FS_NORMAL);
    349         $txt = new Text($aMsg,52,25);
    350         $txt->SetFont(FF_FONT1);
    351         $txt->Align("left","top");
    352         $txt->Stroke($img);
    353         if ($this->iDest) {
    354             $img->Stream($this->iDest);
    355         } else {
    356             $img->Headers();
    357             $img->Stream();
    358         }
    359         if( $aHalt )
    360             die();
    361     }
    362 }
    363 
    364 
    365 
    366 if( ! USE_IMAGE_ERROR_HANDLER ) {
    367         JpGraphError::SetImageFlag(false);
    368 }
     162        $img_iconerror =
     163            'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaV'.
     164            'BMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'.
     165            'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpY'.
     166            'iYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'.
     167            'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACx'.
     168            'IAAAsSAdLdfvwAAAAHdElNRQfTBgISOCqusfs5AAABLUlEQVR4'.
     169            '2tWV3XKCMBBGWfkranCIVClKLd/7P2Q3QsgCxjDTq+6FE2cPH+'.
     170            'xJ0Ogn2lQbsT+Wrs+buAZAV4W5T6Bs0YXBBwpKgEuIu+JERAX6'.
     171            'wM2rHjmDdEITmsQEEmWADgZm6rAjhXsoMGY9B/NZBwJzBvn+e3'.
     172            'wHntCAJdGu9SviwIwoZVDxPB9+Rc0TSEbQr0j3SA1gwdSn6Db0'.
     173            '6Tm1KfV6yzWGQO7zdpvyKLKBDmRFjzeB3LYgK7r6A/noDAfjtS'.
     174            'IXaIzbJSv6WgUebTMV4EoRB8a2mQiQjgtF91HdKDKZ1gtFtQjk'.
     175            'YcWaR5OKOhkYt+ZsTFdJRfPAApOpQYJTNHvCRSJR6SJngQadfc'.
     176            'vd69OLMddVOPCGVnmrFD8bVYd3JXfxXPtLR/+mtv59/ALWiiMx'.
     177            'qL72fwAAAABJRU5ErkJggg==' ;
     178
     179        if( function_exists("imagetypes") )
     180            $supported = imagetypes();
     181        else
     182            $supported = 0;
     183
     184        if( !function_exists('imagecreatefromstring') )
     185            $supported = 0;
     186
     187        if( ob_get_length() || headers_sent() || !($supported & IMG_PNG) ) {
     188            // Special case for headers already sent or that the installation doesn't support
     189            // the PNG format (which the error icon is encoded in).
     190            // Dont return an image since it can't be displayed
     191            die($this->iTitle.' '.$aMsg);               
     192        }
     193
     194        $aMsg = wordwrap($aMsg,55);
     195        $lines = substr_count($aMsg,"\n");
     196
     197        // Create the error icon GD
     198        $erricon = Image::CreateFromString(base64_decode($img_iconerror));   
     199
     200        // Create an image that contains the error text.
     201        $w=400;         
     202        $h=100 + 15*max(0,$lines-3);
     203
     204        $img = new Image($w,$h);
     205
     206
     207        // Drop shadow
     208        $img->SetColor("gray");
     209        $img->FilledRectangle(5,5,$w-1,$h-1,10);
     210        $img->SetColor("gray:0.7");
     211        $img->FilledRectangle(5,5,$w-3,$h-3,10);
     212       
     213        // Window background
     214        $img->SetColor("lightblue");
     215        $img->FilledRectangle(1,1,$w-5,$h-5);
     216        $img->CopyCanvasH($img->img,$erricon,5,30,0,0,40,40);
     217
     218        // Window border
     219        $img->SetColor("black");
     220        $img->Rectangle(1,1,$w-5,$h-5);
     221        $img->Rectangle(0,0,$w-4,$h-4);
     222       
     223        // Window top row
     224        $img->SetColor("darkred");
     225        for($y=3; $y < 18; $y += 2 )
     226            $img->Line(1,$y,$w-6,$y);
     227
     228        // "White shadow"
     229        $img->SetColor("white");
     230
     231        // Left window edge
     232        $img->Line(2,2,2,$h-5);
     233        $img->Line(2,2,$w-6,2);
     234
     235        // "Gray button shadow"
     236        $img->SetColor("darkgray");
     237
     238        // Gray window shadow
     239        $img->Line(2,$h-6,$w-5,$h-6);
     240        $img->Line(3,$h-7,$w-5,$h-7);
     241
     242        // Window title
     243        $m = floor($w/2-5);
     244        $l = 100;
     245        $img->SetColor("lightgray:1.3");
     246        $img->FilledRectangle($m-$l,2,$m+$l,16);
     247
     248        // Stroke text
     249        $img->SetColor("darkred");
     250        $img->SetFont(FF_FONT2,FS_BOLD);
     251        $img->StrokeText($m-50,15,$this->iTitle);
     252        $img->SetColor("black");
     253        $img->SetFont(FF_FONT1,FS_NORMAL);
     254        $txt = new Text($aMsg,52,25);
     255        $txt->Align("left","top");
     256        $txt->Stroke($img);
     257        if ($this->iDest) {
     258           $img->Stream($this->iDest);
     259        } else {
     260            $img->Headers();
     261            $img->Stream();
     262        }
     263        if( $aHalt )
     264            die();
     265    }
     266}
     267
     268
     269// Install the default error handler
     270if( USE_IMAGE_ERROR_HANDLER ) {
     271    JpGraphError::Install("JpGraphErrObjectImg");
     272}
     273else {
     274    JpGraphError::Install("JpGraphErrObject");
     275}
     276
     277
    369278?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_error.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_ERROR.PHP
    4  // Description: Error plot extension for JpGraph
    5  // Created:     2001-01-08
    6  // Ver:         $Id: jpgraph_error.php 1106 2009-02-22 20:16:35Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
    11    
     3// File:        JPGRAPH_ERROR.PHP
     4// Description: Error plot extension for JpGraph
     5// Created:     2001-01-08
     6// Ver:         $Id: jpgraph_error.php 781 2006-10-08 08:07:47Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
     11
    1212//===================================================
    1313// CLASS ErrorPlot
     
    1717class ErrorPlot extends Plot {
    1818    private $errwidth=2;
    19    
    20     //---------------
    21     // CONSTRUCTOR
    22     function __construct($datay,$datax=false) {
    23         parent::__construct($datay,$datax);
    24         $this->numpoints /= 2;
     19//---------------
     20// CONSTRUCTOR
     21    function ErrorPlot($datay,$datax=false) {
     22        $this->Plot($datay,$datax);
     23        $this->numpoints /= 2;
    2524    }
    26     //---------------
    27     // PUBLIC METHODS
    28 
     25//---------------
     26// PUBLIC METHODS
     27       
    2928    // Gets called before any axis are stroked
    3029    function PreStrokeAdjust($graph) {
    31         if( $this->center ) {
    32             $a=0.5; $b=0.5;
    33             ++$this->numpoints;
    34         } else {
    35             $a=0; $b=0;
    36         }
    37         $graph->xaxis->scale->ticks->SetXLabelOffset($a);
    38         $graph->SetTextScaleOff($b);
    39         //$graph->xaxis->scale->ticks->SupressMinorTickMarks();
     30        if( $this->center ) {
     31            $a=0.5; $b=0.5;
     32            ++$this->numpoints;                 
     33        } else {
     34            $a=0; $b=0;
     35        }
     36        $graph->xaxis->scale->ticks->SetXLabelOffset($a);
     37        $graph->SetTextScaleOff($b);                                           
     38        //$graph->xaxis->scale->ticks->SupressMinorTickMarks();
    4039    }
    41 
     40       
    4241    // Method description
    4342    function Stroke($img,$xscale,$yscale) {
    44         $numpoints=count($this->coords[0])/2;
    45         $img->SetColor($this->color);
    46         $img->SetLineWeight($this->weight);
     43        $numpoints=count($this->coords[0])/2;
     44        $img->SetColor($this->color);
     45        $img->SetLineWeight($this->weight);     
    4746
    48         if( isset($this->coords[1]) ) {
    49             if( count($this->coords[1])!=$numpoints )
    50             JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints);
    51             //("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints");
    52             else
    53             $exist_x = true;
    54         }
    55         else
    56         $exist_x = false;
     47        if( isset($this->coords[1]) ) {
     48            if( count($this->coords[1])!=$numpoints )
     49                JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints);
     50//("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints");
     51            else
     52                $exist_x = true;
     53        }
     54        else
     55            $exist_x = false;
    5756
    58         for( $i=0; $i<$numpoints; ++$i) {
    59             if( $exist_x )
    60             $x=$this->coords[1][$i];
    61             else
    62             $x=$i;
     57        for( $i=0; $i<$numpoints; ++$i) {
     58            if( $exist_x )
     59                $x=$this->coords[1][$i];
     60            else
     61                $x=$i;
    6362
    64             if( !is_numeric($x) ||
    65             !is_numeric($this->coords[0][$i*2]) || !is_numeric($this->coords[0][$i*2+1]) ) {
    66                 continue;
    67             }
     63            if( !is_numeric($x) || 
     64                !is_numeric($this->coords[0][$i*2]) || !is_numeric($this->coords[0][$i*2+1]) ) {
     65                continue;
     66            }
    6867
    69             $xt = $xscale->Translate($x);
    70             $yt1 = $yscale->Translate($this->coords[0][$i*2]);
    71             $yt2 = $yscale->Translate($this->coords[0][$i*2+1]);
    72             $img->Line($xt,$yt1,$xt,$yt2);
    73             $img->Line($xt-$this->errwidth,$yt1,$xt+$this->errwidth,$yt1);
    74             $img->Line($xt-$this->errwidth,$yt2,$xt+$this->errwidth,$yt2);
    75         }
    76         return true;
     68            $xt = $xscale->Translate($x);
     69            $yt1 = $yscale->Translate($this->coords[0][$i*2]);
     70            $yt2 = $yscale->Translate($this->coords[0][$i*2+1]);
     71            $img->Line($xt,$yt1,$xt,$yt2);
     72            $img->Line($xt-$this->errwidth,$yt1,$xt+$this->errwidth,$yt1);
     73            $img->Line($xt-$this->errwidth,$yt2,$xt+$this->errwidth,$yt2);
     74        }                       
     75        return true;
    7776    }
    7877} // Class
     
    8786class ErrorLinePlot extends ErrorPlot {
    8887    public $line=null;
    89     //---------------
    90     // CONSTRUCTOR
    91     function __construct($datay,$datax=false) {
    92         parent::__construct($datay,$datax);
    93         // Calculate line coordinates as the average of the error limits
    94         $n = count($datay);
    95         for($i=0; $i < $n; $i+=2 ) {
    96             $ly[]=($datay[$i]+$datay[$i+1])/2;
    97         }
    98         $this->line=new LinePlot($ly,$datax);
     88//---------------
     89// CONSTRUCTOR
     90    function ErrorLinePlot($datay,$datax=false) {
     91        $this->ErrorPlot($datay,$datax);
     92        // Calculate line coordinates as the average of the error limits
     93        $n = count($datay);
     94        for($i=0; $i < $n; $i+=2 ) {
     95            $ly[]=($datay[$i]+$datay[$i+1])/2;
     96        }               
     97        $this->line=new LinePlot($ly,$datax);
    9998    }
    10099
    101     //---------------
    102     // PUBLIC METHODS
     100//---------------
     101// PUBLIC METHODS
    103102    function Legend($graph) {
    104         if( $this->legend != "" )
    105         $graph->legend->Add($this->legend,$this->color);
    106         $this->line->Legend($graph);
     103        if( $this->legend != "" )
     104            $graph->legend->Add($this->legend,$this->color);
     105        $this->line->Legend($graph);
    107106    }
    108      
     107                       
    109108    function Stroke($img,$xscale,$yscale) {
    110         parent::Stroke($img,$xscale,$yscale);
    111         $this->line->Stroke($img,$xscale,$yscale);
     109        parent::Stroke($img,$xscale,$yscale);
     110        $this->line->Stroke($img,$xscale,$yscale);
    112111    }
    113112} // Class
     
    120119class LineErrorPlot extends ErrorPlot {
    121120    public $line=null;
    122     //---------------
    123     // CONSTRUCTOR
     121//---------------
     122// CONSTRUCTOR
    124123    // Data is (val, errdeltamin, errdeltamax)
    125     function __construct($datay,$datax=false) {
    126         $ly=array(); $ey=array();
    127         $n = count($datay);
    128         if( $n % 3 != 0 ) {
    129             JpGraphError::RaiseL(4002);
    130             //('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3');
    131         }
    132         for($i=0; $i < $n; $i+=3 ) {
    133             $ly[]=$datay[$i];
    134             $ey[]=$datay[$i]+$datay[$i+1];
    135             $ey[]=$datay[$i]+$datay[$i+2];
    136         }
    137         parent::__construct($ey,$datax);
    138         $this->line=new LinePlot($ly,$datax);
     124    function LineErrorPlot($datay,$datax=false) {
     125        $ly=array(); $ey=array();
     126        $n = count($datay);
     127        if( $n % 3 != 0 ) {
     128            JpGraphError::RaiseL(4002);
     129//('Error in input data to LineErrorPlot. Number of data points must be a multiple of 3');
     130        }
     131        for($i=0; $i < $n; $i+=3 ) {
     132            $ly[]=$datay[$i];
     133            $ey[]=$datay[$i]+$datay[$i+1];
     134            $ey[]=$datay[$i]+$datay[$i+2];
     135        }               
     136        $this->ErrorPlot($ey,$datax);
     137        $this->line=new LinePlot($ly,$datax);
    139138    }
    140139
    141     //---------------
    142     // PUBLIC METHODS
     140//---------------
     141// PUBLIC METHODS
    143142    function Legend($graph) {
    144         if( $this->legend != "" )
    145         $graph->legend->Add($this->legend,$this->color);
    146         $this->line->Legend($graph);
     143        if( $this->legend != "" )
     144            $graph->legend->Add($this->legend,$this->color);
     145        $this->line->Legend($graph);
    147146    }
    148      
     147                       
    149148    function Stroke($img,$xscale,$yscale) {
    150         parent::Stroke($img,$xscale,$yscale);
    151         $this->line->Stroke($img,$xscale,$yscale);
     149        parent::Stroke($img,$xscale,$yscale);
     150        $this->line->Stroke($img,$xscale,$yscale);
    152151    }
    153152} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_flags.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_FLAGS.PHP
    4 // Description: Class Jpfile. Handles plotmarks
    5 // Created:     2003-06-28
    6 // Ver:         $Id: jpgraph_flags.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        JPGRAPH_FLAGS.PHP
     4// Description: Class Jpfile. Handles plotmarks
     5// Created:     2003-06-28
     6// Ver:         $Id: jpgraph_flags.php 957 2007-12-01 14:00:29Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    259259    private $iFlagCount = -1;
    260260    private $iFlagSetMap = array(
    261     FLAGSIZE1 => 'flags_thumb35x35',
    262     FLAGSIZE2 => 'flags_thumb60x60',
    263     FLAGSIZE3 => 'flags_thumb100x100',
    264     FLAGSIZE4 => 'flags'
    265     );
     261        FLAGSIZE1 => 'flags_thumb35x35',
     262        FLAGSIZE2 => 'flags_thumb60x60',
     263        FLAGSIZE3 => 'flags_thumb100x100',
     264        FLAGSIZE4 => 'flags'
     265        );
    266266
    267267    private $iFlagData ;
    268268    private $iOrdIdx=array();
    269269
    270     function __construct($aSize=FLAGSIZE1) {
    271         switch($aSize) {
    272             case FLAGSIZE1 :
    273             case FLAGSIZE2 :
    274             case FLAGSIZE3 :
    275             case FLAGSIZE4 :
    276                 $file = dirname(__FILE__).'/'.$this->iFlagSetMap[$aSize].'.dat';
    277                 $fp = fopen($file,'rb');
    278                 $rawdata = fread($fp,filesize($file));
    279                 $this->iFlagData = unserialize($rawdata);
    280                 break;
    281             default:
    282                 JpGraphError::RaiseL(5001,$aSize);
    283                 //('Unknown flag size. ('.$aSize.')');
    284         }
    285         $this->iFlagCount = count($this->iCountryNameMap);
     270    function FlagImages($aSize=FLAGSIZE1) {
     271        switch($aSize) {
     272            case FLAGSIZE1 :
     273            case FLAGSIZE2 :
     274            case FLAGSIZE3 :
     275            case FLAGSIZE4 :
     276                $file = dirname(__FILE__).'/'.$this->iFlagSetMap[$aSize].'.dat';
     277                $fp = fopen($file,'rb');
     278                $rawdata = fread($fp,filesize($file));
     279                $this->iFlagData = unserialize($rawdata);
     280            break;
     281            default:
     282                JpGraphError::RaiseL(5001,$aSize);
     283//('Unknown flag size. ('.$aSize.')');
     284        }
     285        $this->iFlagCount = count($this->iCountryNameMap);
    286286    }
    287287
    288288    function GetNum() {
    289         return $this->iFlagCount;
     289        return $this->iFlagCount;
    290290    }
    291291
    292292    function GetImgByName($aName,&$outFullName) {
    293         $idx = $this->GetIdxByName($aName,$outFullName);
    294         return $this->GetImgByIdx($idx);
     293        $idx = $this->GetIdxByName($aName,$outFullName);
     294        return $this->GetImgByIdx($idx);
    295295    }
    296296
    297297    function GetImgByIdx($aIdx) {
    298         if( array_key_exists($aIdx,$this->iFlagData) ) {
    299             $d = $this->iFlagData[$aIdx][1];
    300             return Image::CreateFromString($d);
    301         }
    302         else {
    303             JpGraphError::RaiseL(5002,$aIdx);
    304             //("Flag index \"ï¿œ$aIdx\" does not exist.");
    305         }
     298        if( array_key_exists($aIdx,$this->iFlagData) ) {
     299            $d = $this->iFlagData[$aIdx][1];   
     300            return Image::CreateFromString($d);   
     301        }
     302        else {
     303            JpGraphError::RaiseL(5002,$aIdx);
     304//("Flag index \" $aIdx\" does not exist.");
     305        }
    306306    }
    307307
    308308    function GetIdxByOrdinal($aOrd,&$outFullName) {
    309         $aOrd--;
    310         $n = count($this->iOrdIdx);
    311         if( $n == 0 ) {
    312             $this->iOrdIdx=array();
    313             $i=0;
    314             foreach( $this->iCountryNameMap as $key => $val ) {
    315                 $this->iOrdIdx[$i++] = array($val,$key);
    316             }
    317             $tmp=$this->iOrdIdx[$aOrd];
    318             $outFullName = $tmp[1];
    319             return $tmp[0];
    320              
    321         }
    322         elseif( $aOrd >= 0 && $aOrd < $n ) {
    323             $tmp=$this->iOrdIdx[$aOrd];
    324             $outFullName = $tmp[1];
    325             return $tmp[0];
    326         }
    327         else {
    328             JpGraphError::RaiseL(5003,$aOrd);
    329             //('Invalid ordinal number specified for flag index.');
    330         }
     309        $aOrd--;
     310        $n = count($this->iOrdIdx);
     311        if( $n == 0 ) {
     312            reset($this->iCountryNameMap);
     313            $this->iOrdIdx=array();
     314            $i=0;
     315            while( list($key,$val) = each($this->iCountryNameMap) ) {
     316                $this->iOrdIdx[$i++] = array($val,$key);
     317            }
     318            $tmp=$this->iOrdIdx[$aOrd];
     319            $outFullName = $tmp[1];
     320            return $tmp[0];
     321           
     322        }
     323        elseif( $aOrd >= 0 && $aOrd < $n ) {
     324            $tmp=$this->iOrdIdx[$aOrd];
     325            $outFullName = $tmp[1];
     326            return $tmp[0];
     327        }
     328        else {
     329            JpGraphError::RaiseL(5003,$aOrd);
     330//('Invalid ordinal number specified for flag index.');
     331        }
    331332    }
    332333
    333334    function GetIdxByName($aName,&$outFullName) {
    334335
    335         if( is_integer($aName) ) {
    336             $idx = $this->GetIdxByOrdinal($aName,$outFullName);
    337             return $idx;
    338         }
    339 
    340         $found=false;
    341         $aName = strtolower($aName);
    342         $nlen = strlen($aName);
    343         // Start by trying to match exact index name
    344         foreach( $this->iCountryNameMap as $key => $val ) {
    345             if( $nlen == strlen($val) && $val == $aName )  {
    346                 $found=true;
    347                 break;
    348             }
    349         }
    350         if( !$found ) {
    351             // If the exact index doesn't work try a (partial) full name
    352             foreach( $this->iCountryNameMap as $key => $val ) {
    353                 if( strpos(strtolower($key), $aName) !== false ) {
    354                     $found=true;
    355                     break;
    356                 }
    357             }
    358         }
    359         if( $found ) {
    360             $outFullName = $key;
    361             return $val;
    362         }
    363         else {
    364             JpGraphError::RaiseL(5004,$aName);
    365             //("The (partial) country name \"$aName\" does not have a cooresponding flag image. The flag may still exist but under another name, e.g. insted of \"usa\" try \"united states\".");
    366         }
     336        if( is_integer($aName) ) {
     337            $idx = $this->GetIdxByOrdinal($aName,$outFullName);
     338            return $idx;
     339        }
     340
     341        $found=false;
     342        $aName = strtolower($aName);
     343        $nlen = strlen($aName);
     344        reset($this->iCountryNameMap);
     345        // Start by trying to match exact index name
     346        while( list($key,$val) = each($this->iCountryNameMap) ) {
     347            if( $nlen == strlen($val) && $val == $aName )  {
     348                $found=true;
     349                break;
     350            }
     351        }
     352        if( !$found ) {
     353            reset($this->iCountryNameMap);
     354            // If the exact index doesn't work try a (partial) full name
     355            while( list($key,$val) = each($this->iCountryNameMap) ) {
     356                if( strpos(strtolower($key), $aName) !== false ) {
     357                    $found=true;
     358                    break;
     359                }
     360            }
     361        }
     362        if( $found ) {
     363            $outFullName = $key;
     364            return $val;   
     365        }
     366        else {
     367            JpGraphError::RaiseL(5004,$aName);
     368//("The (partial) country name \"$aName\" does not have a cooresponding flag image. The flag may still exist but under another name, e.g. insted of \"usa\" try \"united states\".");
     369        }
    367370    }
    368371}
  • trunk/client/modules/Elezioni/grafici/jpgraph_gantt.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_GANTT.PHP
    4  // Description: JpGraph Gantt plot extension
    5  // Created:     2001-11-12
    6  // Ver:         $Id: jpgraph_gantt.php 1809 2009-09-09 13:07:33Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
    11 
    12 require_once('jpgraph_plotband.php');
    13 require_once('jpgraph_iconplot.php');
     3// File:        JPGRAPH_GANTT.PHP
     4// Description: JpGraph Gantt plot extension
     5// Created:     2001-11-12
     6// Ver:         $Id: jpgraph_gantt.php 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
     11
     12require_once('jpgraph_plotband.php'); 
     13require_once('jpgraph_iconplot.php'); 
    1414require_once('jpgraph_plotmark.inc.php');
    1515
    1616// Maximum size for Automatic Gantt chart
    17 define('MAX_GANTTIMG_SIZE_W',8000);
     17define('MAX_GANTTIMG_SIZE_W',4000);
    1818define('MAX_GANTTIMG_SIZE_H',5000);
    1919
     
    2727
    2828// Bar patterns
    29 define("GANTT_RDIAG",BAND_RDIAG); // Right diagonal lines
     29define("GANTT_RDIAG",BAND_RDIAG);       // Right diagonal lines
    3030define("GANTT_LDIAG",BAND_LDIAG); // Left diagonal lines
    3131define("GANTT_SOLID",BAND_SOLID); // Solid one color
     
    4040
    4141// Locales. ONLY KEPT FOR BACKWARDS COMPATIBILITY
    42 // You should use the proper locale strings directly
    43 // from now on.
     42// You should use the proper locale strings directly 
     43// from now on. 
    4444define("LOCALE_EN","en_UK");
    4545define("LOCALE_SV","sv_SE");
     
    5050
    5151// Style for minute header
    52 define("MINUTESTYLE_MM",0);  // 15
    53 define("MINUTESTYLE_CUSTOM",2);  // Custom format
     52define("MINUTESTYLE_MM",0);             // 15
     53define("MINUTESTYLE_CUSTOM",2);         // Custom format
    5454
    5555
    5656// Style for hour header
    57 define("HOURSTYLE_HM24",0);  // 13:10
    58 define("HOURSTYLE_HMAMPM",1);  // 1:10pm
    59 define("HOURSTYLE_H24",2);  // 13
    60 define("HOURSTYLE_HAMPM",3);  // 1pm
    61 define("HOURSTYLE_CUSTOM",4);  // User defined
     57define("HOURSTYLE_HM24",0);             // 13:10
     58define("HOURSTYLE_HMAMPM",1);           // 1:10pm
     59define("HOURSTYLE_H24",2);              // 13
     60define("HOURSTYLE_HAMPM",3);            // 1pm
     61define("HOURSTYLE_CUSTOM",4);           // User defined
    6262
    6363// Style for day header
    64 define("DAYSTYLE_ONELETTER",0);  // "M"
    65 define("DAYSTYLE_LONG",1);  // "Monday"
    66 define("DAYSTYLE_LONGDAYDATE1",2); // "Monday 23 Jun"
    67 define("DAYSTYLE_LONGDAYDATE2",3); // "Monday 23 Jun 2003"
    68 define("DAYSTYLE_SHORT",4);  // "Mon"
    69 define("DAYSTYLE_SHORTDAYDATE1",5); // "Mon 23/6"
    70 define("DAYSTYLE_SHORTDAYDATE2",6); // "Mon 23 Jun"
    71 define("DAYSTYLE_SHORTDAYDATE3",7); // "Mon 23"
    72 define("DAYSTYLE_SHORTDATE1",8); // "23/6"
    73 define("DAYSTYLE_SHORTDATE2",9); // "23 Jun"
    74 define("DAYSTYLE_SHORTDATE3",10); // "Mon 23"
    75 define("DAYSTYLE_SHORTDATE4",11); // "23"
    76 define("DAYSTYLE_CUSTOM",12);  // "M"
     64define("DAYSTYLE_ONELETTER",0);         // "M"
     65define("DAYSTYLE_LONG",1);              // "Monday"
     66define("DAYSTYLE_LONGDAYDATE1",2);      // "Monday 23 Jun"
     67define("DAYSTYLE_LONGDAYDATE2",3);      // "Monday 23 Jun 2003"
     68define("DAYSTYLE_SHORT",4);             // "Mon"
     69define("DAYSTYLE_SHORTDAYDATE1",5);     // "Mon 23/6"
     70define("DAYSTYLE_SHORTDAYDATE2",6);     // "Mon 23 Jun"
     71define("DAYSTYLE_SHORTDAYDATE3",7);     // "Mon 23"
     72define("DAYSTYLE_SHORTDATE1",8);        // "23/6"
     73define("DAYSTYLE_SHORTDATE2",9);        // "23 Jun"
     74define("DAYSTYLE_SHORTDATE3",10);       // "Mon 23"
     75define("DAYSTYLE_SHORTDATE4",11);       // "23"
     76define("DAYSTYLE_CUSTOM",12);           // "M"
    7777
    7878// Styles for week header
     
    128128if (!function_exists('array_fill')) {
    129129    function array_fill($iStart, $iLen, $vValue) {
    130         $aResult = array();
    131         for ($iCount = $iStart; $iCount < $iLen + $iStart; $iCount++) {
    132             $aResult[$iCount] = $vValue;
    133         }
    134         return $aResult;
     130        $aResult = array();
     131        for ($iCount = $iStart; $iCount < $iLen + $iStart; $iCount++) {
     132            $aResult[$iCount] = $vValue;
     133        }
     134        return $aResult;
    135135    }
    136136}
     
    138138//===================================================
    139139// CLASS GanttActivityInfo
    140 // Description:
     140// Description: 
    141141//===================================================
    142142class GanttActivityInfo {
     
    153153    private $iHeaderAlign='center';
    154154
    155     function __construct() {
    156         $this->vgrid = new LineProperty();
     155    function GanttActivityInfo() {
     156        $this->vgrid = new LineProperty();
    157157    }
    158158
    159159    function Hide($aF=true) {
    160         $this->iShow=!$aF;
     160        $this->iShow=!$aF;
    161161    }
    162162
    163163    function Show($aF=true) {
    164         $this->iShow=$aF;
     164        $this->iShow=$aF;
    165165    }
    166166
    167167    // Specify font
    168168    function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
    169         $this->iFFamily = $aFFamily;
    170         $this->iFStyle = $aFStyle;
    171         $this->iFSize = $aFSize;
     169        $this->iFFamily = $aFFamily;
     170        $this->iFStyle  = $aFStyle;
     171        $this->iFSize    = $aFSize;
    172172    }
    173173
    174174    function SetStyle($aStyle) {
    175         $this->iStyle = $aStyle;
     175        $this->iStyle = $aStyle;
    176176    }
    177177
    178178    function SetColumnMargin($aLeft,$aRight) {
    179         $this->iLeftColMargin = $aLeft;
    180         $this->iRightColMargin = $aRight;
     179        $this->iLeftColMargin = $aLeft;
     180        $this->iRightColMargin = $aRight;
    181181    }
    182182
    183183    function SetFontColor($aFontColor) {
    184         $this->iFontColor = $aFontColor;
     184        $this->iFontColor = $aFontColor;
    185185    }
    186186
    187187    function SetColor($aColor) {
    188         $this->iColor = $aColor;
     188        $this->iColor = $aColor;
    189189    }
    190190
    191191    function SetBackgroundColor($aColor) {
    192         $this->iBackgroundColor = $aColor;
     192        $this->iBackgroundColor = $aColor;
    193193    }
    194194
    195195    function SetColTitles($aTitles,$aWidth=null) {
    196         $this->iTitles = $aTitles;
    197         $this->iWidth = $aWidth;
     196        $this->iTitles = $aTitles;
     197        $this->iWidth = $aWidth;
    198198    }
    199199
    200200    function SetMinColWidth($aWidths) {
    201         $n = min(count($this->iTitles),count($aWidths));
    202         for($i=0; $i < $n; ++$i ) {
    203             if( !empty($aWidths[$i]) ) {
    204                 if( empty($this->iWidth[$i]) ) {
    205                     $this->iWidth[$i] = $aWidths[$i];
    206                 }
    207                 else {
    208                     $this->iWidth[$i] = max($this->iWidth[$i],$aWidths[$i]);
    209                 }
    210             }
    211         }
     201        $n = min(count($this->iTitles),count($aWidths));
     202        for($i=0; $i < $n; ++$i ) {
     203            if( !empty($aWidths[$i]) ) {
     204                if( empty($this->iWidth[$i]) ) {
     205                    $this->iWidth[$i] = $aWidths[$i];
     206                }
     207                else {
     208                    $this->iWidth[$i] = max($this->iWidth[$i],$aWidths[$i]);
     209                }
     210            }
     211        }
    212212    }
    213213
    214214    function GetWidth($aImg) {
    215         $txt = new TextProperty();
    216         $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    217         $n = count($this->iTitles) ;
    218         $rm=$this->iRightColMargin;
    219         $w = 0;
    220         for($h=0, $i=0; $i < $n; ++$i ) {
    221             $w += $this->iLeftColMargin;
    222             $txt->Set($this->iTitles[$i]);
    223             if( !empty($this->iWidth[$i]) ) {
    224                 $w1 = max($txt->GetWidth($aImg)+$rm,$this->iWidth[$i]);
    225             }
    226             else {
    227                 $w1 = $txt->GetWidth($aImg)+$rm;
    228             }
    229             $this->iWidth[$i] = $w1;
    230             $w += $w1;
    231             $h = max($h,$txt->GetHeight($aImg));
    232         }
    233         $this->iHeight = $h+$this->iTopHeaderMargin;
     215        $txt = new TextProperty();
     216        $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     217        $n = count($this->iTitles) ;
     218        $rm=$this->iRightColMargin;
     219        $w = 0;
     220        for($h=0, $i=0; $i < $n; ++$i ) {
     221            $w += $this->iLeftColMargin;
     222            $txt->Set($this->iTitles[$i]);
     223            if( !empty($this->iWidth[$i]) ) {
     224                $w1 = max($txt->GetWidth($aImg)+$rm,$this->iWidth[$i]);
     225            }
     226            else {
     227                $w1 = $txt->GetWidth($aImg)+$rm;
     228            }
     229            $this->iWidth[$i] = $w1;
     230            $w += $w1;
     231            $h = max($h,$txt->GetHeight($aImg));
     232        }
     233        $this->iHeight = $h+$this->iTopHeaderMargin;
    234234        $txt='';
    235         return $w;
    236     }
    237 
     235        return $w;
     236    }
     237   
    238238    function GetColStart($aImg,&$aStart,$aAddLeftMargin=false) {
    239         $n = count($this->iTitles) ;
    240         $adj = $aAddLeftMargin ? $this->iLeftColMargin : 0;
    241         $aStart=array($aImg->left_margin+$adj);
    242         for( $i=1; $i < $n; ++$i ) {
    243             $aStart[$i] = $aStart[$i-1]+$this->iLeftColMargin+$this->iWidth[$i-1];
    244         }
    245     }
    246 
     239        $n = count($this->iTitles) ;
     240        $adj = $aAddLeftMargin ? $this->iLeftColMargin : 0;
     241        $aStart=array($aImg->left_margin+$adj);
     242        for( $i=1; $i < $n; ++$i ) {
     243            $aStart[$i] = $aStart[$i-1]+$this->iLeftColMargin+$this->iWidth[$i-1];
     244        }
     245    }
     246   
    247247    // Adjust headers left, right or centered
    248248    function SetHeaderAlign($aAlign) {
    249         $this->iHeaderAlign=$aAlign;
     249        $this->iHeaderAlign=$aAlign;
    250250    }
    251251
    252252    function Stroke($aImg,$aXLeft,$aYTop,$aXRight,$aYBottom,$aUseTextHeight=false) {
    253253
    254         if( !$this->iShow ) return;
    255 
    256         $txt = new TextProperty();
    257         $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    258         $txt->SetColor($this->iFontColor);
    259         $txt->SetAlign($this->iHeaderAlign,'top');
    260         $n=count($this->iTitles);
    261 
    262         if( $n == 0 )
    263         return;
    264 
    265         $x = $aXLeft;
    266         $h = $this->iHeight;
    267         $yTop = $aUseTextHeight ? $aYBottom-$h-$this->iTopColMargin-$this->iBottomColMargin : $aYTop ;
    268 
    269         if( $h < 0 ) {
    270             JpGraphError::RaiseL(6001);
    271             //('Internal error. Height for ActivityTitles is < 0');
    272         }
    273 
    274         $aImg->SetLineWeight(1);
    275         // Set background color
    276         $aImg->SetColor($this->iBackgroundColor);
    277         $aImg->FilledRectangle($aXLeft,$yTop,$aXRight,$aYBottom-1);
    278 
    279         if( $this->iStyle == 1 ) {
    280             // Make a 3D effect
    281             $aImg->SetColor('white');
    282             $aImg->Line($aXLeft,$yTop+1,$aXRight,$yTop+1);
    283         }
    284 
    285         for($i=0; $i < $n; ++$i ) {
    286             if( $this->iStyle == 1 ) {
    287                 // Make a 3D effect
    288                 $aImg->SetColor('white');
    289                 $aImg->Line($x+1,$yTop,$x+1,$aYBottom);
    290             }
    291             $x += $this->iLeftColMargin;
    292             $txt->Set($this->iTitles[$i]);
    293 
    294             // Adjust the text anchor position according to the choosen alignment
    295             $xp = $x;
    296             if( $this->iHeaderAlign == 'center' ) {
    297                 $xp = (($x-$this->iLeftColMargin)+($x+$this->iWidth[$i]))/2;
    298             }
    299             elseif( $this->iHeaderAlign == 'right' ) {
    300                 $xp = $x +$this->iWidth[$i]-$this->iRightColMargin;
    301             }
    302 
    303             $txt->Stroke($aImg,$xp,$yTop+$this->iTopHeaderMargin);
    304             $x += $this->iWidth[$i];
    305             if( $i < $n-1 ) {
    306                 $aImg->SetColor($this->iColor);
    307                 $aImg->Line($x,$yTop,$x,$aYBottom);
    308             }
    309         }
    310 
    311         $aImg->SetColor($this->iColor);
    312         $aImg->Line($aXLeft,$yTop, $aXRight,$yTop);
    313 
    314         // Stroke vertical column dividers
    315         $cols=array();
    316         $this->GetColStart($aImg,$cols);
    317         $n=count($cols);
    318         for( $i=1; $i < $n; ++$i ) {
    319             $this->vgrid->Stroke($aImg,$cols[$i],$aYBottom,$cols[$i],
    320             $aImg->height - $aImg->bottom_margin);
    321         }
     254        if( !$this->iShow ) return;
     255
     256        $txt = new TextProperty();
     257        $txt->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     258        $txt->SetColor($this->iFontColor);
     259        $txt->SetAlign($this->iHeaderAlign,'top');
     260        $n=count($this->iTitles);
     261
     262        if( $n == 0 )
     263            return;
     264       
     265        $x = $aXLeft;
     266        $h = $this->iHeight;
     267        $yTop = $aUseTextHeight ? $aYBottom-$h-$this->iTopColMargin-$this->iBottomColMargin : $aYTop ;
     268
     269        if( $h < 0 ) {
     270            JpGraphError::RaiseL(6001);
     271//('Internal error. Height for ActivityTitles is < 0');
     272        }
     273
     274        $aImg->SetLineWeight(1);
     275        // Set background color
     276        $aImg->SetColor($this->iBackgroundColor);
     277        $aImg->FilledRectangle($aXLeft,$yTop,$aXRight,$aYBottom-1);
     278
     279        if( $this->iStyle == 1 ) {
     280            // Make a 3D effect
     281            $aImg->SetColor('white');
     282            $aImg->Line($aXLeft,$yTop+1,
     283                        $aXRight,$yTop+1);
     284        }
     285       
     286        for($i=0; $i < $n; ++$i ) {
     287            if( $this->iStyle == 1 ) {
     288                // Make a 3D effect
     289                $aImg->SetColor('white');
     290                $aImg->Line($x+1,$yTop,$x+1,$aYBottom);
     291            }
     292            $x += $this->iLeftColMargin;
     293            $txt->Set($this->iTitles[$i]);
     294           
     295            // Adjust the text anchor position according to the choosen alignment
     296            $xp = $x;
     297            if( $this->iHeaderAlign == 'center' ) {
     298                $xp = (($x-$this->iLeftColMargin)+($x+$this->iWidth[$i]))/2;
     299            }
     300            elseif( $this->iHeaderAlign == 'right' ) {
     301                $xp = $x +$this->iWidth[$i]-$this->iRightColMargin;
     302            }
     303                   
     304            $txt->Stroke($aImg,$xp,$yTop+$this->iTopHeaderMargin);
     305            $x += $this->iWidth[$i];
     306            if( $i < $n-1 ) {
     307                $aImg->SetColor($this->iColor);
     308                $aImg->Line($x,$yTop,$x,$aYBottom);
     309            }
     310        }
     311
     312        $aImg->SetColor($this->iColor);
     313        $aImg->Line($aXLeft,$yTop, $aXRight,$yTop);
     314
     315        // Stroke vertical column dividers
     316        $cols=array();
     317        $this->GetColStart($aImg,$cols);
     318        $n=count($cols);
     319        for( $i=1; $i < $n; ++$i ) {
     320            $this->vgrid->Stroke($aImg,$cols[$i],$aYBottom,$cols[$i],
     321                                    $aImg->height - $aImg->bottom_margin);
     322        }
    322323    }
    323324}
     
    329330//===================================================
    330331class GanttGraph extends Graph {
    331     public $scale;  // Public accessible
     332    public $scale;              // Public accessible
    332333    public $hgrid=null;
    333     private $iObj=array();    // Gantt objects
    334     private $iLabelHMarginFactor=0.2; // 10% margin on each side of the labels
    335     private $iLabelVMarginFactor=0.4; // 40% margin on top and bottom of label
    336     private $iLayout=GANTT_FROMTOP; // Could also be GANTT_EVEN
     334    private $iObj=array();                              // Gantt objects
     335    private $iLabelHMarginFactor=0.2;   // 10% margin on each side of the labels
     336    private $iLabelVMarginFactor=0.4;   // 40% margin on top and bottom of label
     337    private $iLayout=GANTT_FROMTOP;     // Could also be GANTT_EVEN
    337338    private $iSimpleFont = FF_FONT1,$iSimpleFontSize=11;
    338339    private $iSimpleStyle=GANTT_RDIAG,$iSimpleColor='yellow',$iSimpleBkgColor='red';
    339340    private $iSimpleProgressBkgColor='gray',$iSimpleProgressColor='darkgreen';
    340341    private $iSimpleProgressStyle=GANTT_SOLID;
    341     private $iZoomFactor = 1.0;
    342     //---------------
    343     // CONSTRUCTOR
     342//---------------
     343// CONSTRUCTOR 
    344344    // Create a new gantt graph
    345     function __construct($aWidth=0,$aHeight=0,$aCachedName="",$aTimeOut=0,$aInline=true) {
    346 
    347         // Backward compatibility
    348         if( $aWidth == -1 ) $aWidth=0;
    349         if( $aHeight == -1 ) $aHeight=0;
    350 
    351         if( $aWidth<  0 || $aHeight < 0 ) {
    352             JpgraphError::RaiseL(6002);
    353             //("You can't specify negative sizes for Gantt graph dimensions. Use 0 to indicate that you want the library to automatically determine a dimension.");
    354         }
    355         parent::__construct($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline);
    356         $this->scale = new GanttScale($this->img);
    357 
    358         // Default margins
    359         $this->img->SetMargin(15,17,25,15);
    360 
    361         $this->hgrid = new HorizontalGridLine();
    362 
    363         $this->scale->ShowHeaders(GANTT_HWEEK|GANTT_HDAY);
    364         $this->SetBox();
    365     }
    366 
    367     //---------------
    368     // PUBLIC METHODS
    369 
    370     //
     345    function GanttGraph($aWidth=0,$aHeight=0,$aCachedName="",$aTimeOut=0,$aInline=true) {
     346
     347        // Backward compatibility
     348        if( $aWidth == -1 ) $aWidth=0;
     349        if( $aHeight == -1 ) $aHeight=0;
     350
     351        if( $aWidth<  0 || $aHeight < 0 ) {
     352            JpgraphError::RaiseL(6002);
     353//("You can't specify negative sizes for Gantt graph dimensions. Use 0 to indicate that you want the library to automatically determine a dimension.");
     354        }
     355        Graph::Graph($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline);         
     356        $this->scale = new GanttScale($this->img);
     357
     358        // Default margins
     359        $this->img->SetMargin(15,17,25,15);
     360
     361        $this->hgrid = new HorizontalGridLine();
     362               
     363        $this->scale->ShowHeaders(GANTT_HWEEK|GANTT_HDAY);
     364        $this->SetBox();
     365    }
     366       
     367//---------------
     368// PUBLIC METHODS
     369
     370    // 
    371371
    372372    function SetSimpleFont($aFont,$aSize) {
    373         $this->iSimpleFont = $aFont;
    374         $this->iSimpleFontSize = $aSize;
     373        $this->iSimpleFont = $aFont;
     374        $this->iSimpleFontSize = $aSize;
    375375    }
    376376
    377377    function SetSimpleStyle($aBand,$aColor,$aBkgColor) {
    378         $this->iSimpleStyle = $aBand;
    379         $this->iSimpleColor = $aColor;
    380         $this->iSimpleBkgColor = $aBkgColor;
     378        $this->iSimpleStyle = $aBand;
     379        $this->iSimpleColor = $aColor;
     380        $this->iSimpleBkgColor = $aBkgColor;
    381381    }
    382382
    383383    // A utility function to help create basic Gantt charts
    384384    function CreateSimple($data,$constrains=array(),$progress=array()) {
    385         $num = count($data);
    386         for( $i=0; $i < $num; ++$i) {
    387             switch( $data[$i][1] ) {
    388                 case ACTYPE_GROUP:
    389                     // Create a slightly smaller height bar since the
    390                     // "wings" at the end will make it look taller
    391                     $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',8);
    392                     $a->title->SetFont($this->iSimpleFont,FS_BOLD,$this->iSimpleFontSize);
    393                     $a->rightMark->Show();
    394                     $a->rightMark->SetType(MARK_RIGHTTRIANGLE);
    395                     $a->rightMark->SetWidth(8);
    396                     $a->rightMark->SetColor('black');
    397                     $a->rightMark->SetFillColor('black');
    398 
    399                     $a->leftMark->Show();
    400                     $a->leftMark->SetType(MARK_LEFTTRIANGLE);
    401                     $a->leftMark->SetWidth(8);
    402                     $a->leftMark->SetColor('black');
    403                     $a->leftMark->SetFillColor('black');
    404 
    405                     $a->SetPattern(BAND_SOLID,'black');
    406                     $csimpos = 6;
    407                     break;
    408 
    409                 case ACTYPE_NORMAL:
    410                     $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',10);
    411                     $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize);
    412                     $a->SetPattern($this->iSimpleStyle,$this->iSimpleColor);
    413                     $a->SetFillColor($this->iSimpleBkgColor);
    414                     // Check if this activity should have a constrain line
    415                     $n = count($constrains);
    416                     for( $j=0; $j < $n; ++$j ) {
    417                         if( empty($constrains[$j]) || (count($constrains[$j]) != 3) ) {
    418                             JpGraphError::RaiseL(6003,$j);
    419                             //("Invalid format for Constrain parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Constrain-To,Constrain-Type)");
    420                         }
    421                         if( $constrains[$j][0]==$data[$i][0] ) {
    422                             $a->SetConstrain($constrains[$j][1],$constrains[$j][2],'black',ARROW_S2,ARROWT_SOLID);
    423                         }
    424                     }
    425 
    426                     // Check if this activity have a progress bar
    427                     $n = count($progress);
    428                     for( $j=0; $j < $n; ++$j ) {
    429 
    430                         if( empty($progress[$j]) || (count($progress[$j]) != 2) ) {
    431                             JpGraphError::RaiseL(6004,$j);
    432                             //("Invalid format for Progress parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Progress)");
    433                         }
    434                         if( $progress[$j][0]==$data[$i][0] ) {
    435                             $a->progress->Set($progress[$j][1]);
    436                             $a->progress->SetPattern($this->iSimpleProgressStyle,
    437                             $this->iSimpleProgressColor);
    438                             $a->progress->SetFillColor($this->iSimpleProgressBkgColor);
    439                             //$a->progress->SetPattern($progress[$j][2],$progress[$j][3]);
    440                             break;
    441                         }
    442                     }
    443                     $csimpos = 6;
    444                     break;
    445 
    446                 case ACTYPE_MILESTONE:
    447                     $a = new MileStone($data[$i][0],$data[$i][2],$data[$i][3]);
    448                     $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize);
    449                     $a->caption->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize);
    450                     $csimpos = 5;
    451                     break;
    452                 default:
    453                     die('Unknown activity type');
    454                     break;
    455             }
    456 
    457             // Setup caption
    458             $a->caption->Set($data[$i][$csimpos-1]);
    459 
    460             // Check if this activity should have a CSIM targetï¿œ?
    461             if( !empty($data[$i][$csimpos]) ) {
    462                 $a->SetCSIMTarget($data[$i][$csimpos]);
    463                 $a->SetCSIMAlt($data[$i][$csimpos+1]);
    464             }
    465             if( !empty($data[$i][$csimpos+2]) ) {
    466                 $a->title->SetCSIMTarget($data[$i][$csimpos+2]);
    467                 $a->title->SetCSIMAlt($data[$i][$csimpos+3]);
    468             }
    469 
    470             $this->Add($a);
    471         }
    472     }
    473 
    474     // Set user specified scale zoom factor when auto sizing is used
    475     function SetZoomFactor($aZoom) {
    476         $this->iZoomFactor = $aZoom;
    477     }
    478 
    479 
     385        $num = count($data);
     386        for( $i=0; $i < $num; ++$i) {
     387            switch( $data[$i][1] ) {
     388                case ACTYPE_GROUP:
     389                    // Create a slightly smaller height bar since the
     390                    // "wings" at the end will make it look taller
     391                    $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',8);
     392                    $a->title->SetFont($this->iSimpleFont,FS_BOLD,$this->iSimpleFontSize);             
     393                    $a->rightMark->Show();
     394                    $a->rightMark->SetType(MARK_RIGHTTRIANGLE);
     395                    $a->rightMark->SetWidth(8);
     396                    $a->rightMark->SetColor('black');
     397                    $a->rightMark->SetFillColor('black');
     398           
     399                    $a->leftMark->Show();
     400                    $a->leftMark->SetType(MARK_LEFTTRIANGLE);
     401                    $a->leftMark->SetWidth(8);
     402                    $a->leftMark->SetColor('black');
     403                    $a->leftMark->SetFillColor('black');
     404           
     405                    $a->SetPattern(BAND_SOLID,'black');
     406                    $csimpos = 6;
     407                    break;
     408               
     409                case ACTYPE_NORMAL:
     410                    $a = new GanttBar($data[$i][0],$data[$i][2],$data[$i][3],$data[$i][4],'',10);
     411                    $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize);
     412                    $a->SetPattern($this->iSimpleStyle,$this->iSimpleColor);
     413                    $a->SetFillColor($this->iSimpleBkgColor);
     414                    // Check if this activity should have a constrain line
     415                    $n = count($constrains);
     416                    for( $j=0; $j < $n; ++$j ) {
     417                        if( empty($constrains[$j]) || (count($constrains[$j]) != 3) ) {
     418                            JpGraphError::RaiseL(6003,$j);
     419//("Invalid format for Constrain parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Constrain-To,Constrain-Type)");   
     420                        }
     421                        if( $constrains[$j][0]==$data[$i][0] ) {
     422                            $a->SetConstrain($constrains[$j][1],$constrains[$j][2],'black',ARROW_S2,ARROWT_SOLID);   
     423                        }
     424                    }
     425
     426                    // Check if this activity have a progress bar
     427                    $n = count($progress);
     428                    for( $j=0; $j < $n; ++$j ) {
     429                       
     430                        if( empty($progress[$j]) || (count($progress[$j]) != 2) ) {
     431                            JpGraphError::RaiseL(6004,$j);
     432//("Invalid format for Progress parameter at index=$j in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Progress)");     
     433                        }
     434                        if( $progress[$j][0]==$data[$i][0] ) {
     435                            $a->progress->Set($progress[$j][1]);
     436                            $a->progress->SetPattern($this->iSimpleProgressStyle,
     437                                                     $this->iSimpleProgressColor);
     438                            $a->progress->SetFillColor($this->iSimpleProgressBkgColor);
     439                            //$a->progress->SetPattern($progress[$j][2],$progress[$j][3]);
     440                            break;
     441                        }
     442                    }
     443                    $csimpos = 6;
     444                    break;
     445
     446                case ACTYPE_MILESTONE:
     447                    $a = new MileStone($data[$i][0],$data[$i][2],$data[$i][3]);
     448                    $a->title->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize);
     449                    $a->caption->SetFont($this->iSimpleFont,FS_NORMAL,$this->iSimpleFontSize);
     450                    $csimpos = 5;
     451                    break;
     452                default:
     453                    die('Unknown activity type');
     454                    break;
     455            }
     456
     457            // Setup caption
     458            $a->caption->Set($data[$i][$csimpos-1]);
     459
     460            // Check if this activity should have a CSIM target ?
     461            if( !empty($data[$i][$csimpos]) ) {
     462                $a->SetCSIMTarget($data[$i][$csimpos]);
     463                $a->SetCSIMAlt($data[$i][$csimpos+1]);
     464            }
     465            if( !empty($data[$i][$csimpos+2]) ) {
     466                $a->title->SetCSIMTarget($data[$i][$csimpos+2]);
     467                $a->title->SetCSIMAlt($data[$i][$csimpos+3]);
     468            }
     469
     470            $this->Add($a);
     471        }
     472    }
     473
     474       
    480475    // Set what headers should be shown
    481476    function ShowHeaders($aFlg) {
    482         $this->scale->ShowHeaders($aFlg);
    483     }
    484 
    485     // Specify the fraction of the font height that should be added
     477        $this->scale->ShowHeaders($aFlg);
     478    }
     479       
     480    // Specify the fraction of the font height that should be added 
    486481    // as vertical margin
    487482    function SetLabelVMarginFactor($aVal) {
    488         $this->iLabelVMarginFactor = $aVal;
     483        $this->iLabelVMarginFactor = $aVal;
    489484    }
    490485
    491486    // Synonym to the method above
    492487    function SetVMarginFactor($aVal) {
    493         $this->iLabelVMarginFactor = $aVal;
    494     }
    495 
    496 
     488        $this->iLabelVMarginFactor = $aVal;
     489    }
     490       
     491       
    497492    // Add a new Gantt object
    498493    function Add($aObject) {
    499         if( is_array($aObject) && count($aObject) > 0 ) {
    500             $cl = $aObject[0];
    501             if( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) {
    502                 $this->AddIcon($aObject);
    503             }
    504             elseif( class_exists('Text',false) && ($cl instanceof Text) ) {
    505                 $this->AddText($aObject);
    506             }
    507             else {
    508                 $n = count($aObject);
    509                 for($i=0; $i < $n; ++$i)
    510                 $this->iObj[] = $aObject[$i];
    511             }
    512         }
    513         else {
    514             if( class_exists('IconPlot',false) && ($aObject instanceof IconPlot) ) {
    515                 $this->AddIcon($aObject);
    516             }
    517             elseif( class_exists('Text',false) && ($aObject instanceof Text) ) {
    518                 $this->AddText($aObject);
    519             }
    520             else {
    521                 $this->iObj[] = $aObject;
    522             }
    523         }
    524     }
    525 
    526         function StrokeTexts() {
    527         // Stroke any user added text objects
    528         if( $this->texts != null ) {
    529                 $n = count($this->texts);
    530             for($i=0; $i < $n; ++$i) {
    531                 if( $this->texts[$i]->iScalePosX !== null && $this->texts[$i]->iScalePosY !== null ) {
    532                         $x = $this->scale->TranslateDate($this->texts[$i]->iScalePosX);
    533                         $y = $this->scale->TranslateVertPos($this->texts[$i]->iScalePosY);
    534                         $y -= $this->scale->GetVertSpacing()/2;
    535                 }
    536                 else {
    537                         $x = $y = null;
    538                 }
    539                 $this->texts[$i]->Stroke($this->img,$x,$y);
    540             }
    541         }
    542         }
     494        if( is_array($aObject) && count($aObject) > 0 ) {
     495            $cl = $aObject[0];
     496            if( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) {
     497                $this->AddIcon($aObject);
     498            }
     499            else {
     500                $n = count($aObject);
     501                for($i=0; $i < $n; ++$i)
     502                    $this->iObj[] = $aObject[$i];
     503            }
     504        }
     505        else {
     506            if( class_exists('IconPlot',false) && ($aObject instanceof IconPlot) ) {
     507                $this->AddIcon($aObject);
     508            }
     509            else {         
     510                $this->iObj[] = $aObject;
     511            }
     512        }
     513    }
    543514
    544515    // Override inherit method from Graph and give a warning message
    545516    function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) {
    546         JpGraphError::RaiseL(6005);
    547         //("SetScale() is not meaningfull with Gantt charts.");
     517        JpGraphError::RaiseL(6005);
     518//("SetScale() is not meaningfull with Gantt charts.");
    548519    }
    549520
     
    551522    // automtically determined from the input data)
    552523    function SetDateRange($aStart,$aEnd) {
    553         // Adjust the start and end so that the indicate the
    554         // begining and end of respective start and end days
    555         if( strpos($aStart,':') === false )
    556         $aStart = date('Y-m-d 00:00',strtotime($aStart));
    557         if( strpos($aEnd,':') === false )
    558         $aEnd = date('Y-m-d 23:59',strtotime($aEnd));
    559         $this->scale->SetRange($aStart,$aEnd);
    560     }
    561 
     524        // Adjust the start and end so that the indicate the
     525        // begining and end of respective start and end days
     526        if( strpos($aStart,':') === false )
     527            $aStart = date('Y-m-d 00:00',strtotime($aStart));
     528        if( strpos($aEnd,':') === false )
     529            $aEnd = date('Y-m-d 23:59',strtotime($aEnd));
     530        $this->scale->SetRange($aStart,$aEnd);
     531    }
     532       
    562533    // Get the maximum width of the activity titles columns for the bars
    563534    // The name is lightly misleading since we from now on can have
     
    565536    // it only supported a single label, hence the name.
    566537    function GetMaxLabelWidth() {
    567         $m=10;
    568         if( $this->iObj != null ) {
    569             $marg = $this->scale->actinfo->iLeftColMargin+$this->scale->actinfo->iRightColMargin;
    570             $n = count($this->iObj);
    571             for($i=0; $i < $n; ++$i) {
    572                 if( !empty($this->iObj[$i]->title) ) {
    573                     if( $this->iObj[$i]->title->HasTabs() ) {
    574                         list($tot,$w) = $this->iObj[$i]->title->GetWidth($this->img,true);
    575                         $m=max($m,$tot);
    576                     }
    577                     else
    578                     $m=max($m,$this->iObj[$i]->title->GetWidth($this->img));
    579                 }
    580             }
    581         }
    582         return $m;
    583     }
    584 
     538        $m=10;
     539        if( $this->iObj != null ) {
     540            $marg = $this->scale->actinfo->iLeftColMargin+$this->scale->actinfo->iRightColMargin;
     541            $n = count($this->iObj);
     542            for($i=0; $i < $n; ++$i) {
     543                if( !empty($this->iObj[$i]->title) ) {
     544                    if( $this->iObj[$i]->title->HasTabs() ) {
     545                        list($tot,$w) = $this->iObj[$i]->title->GetWidth($this->img,true);
     546                        $m=max($m,$tot);
     547                    }
     548                    else
     549                        $m=max($m,$this->iObj[$i]->title->GetWidth($this->img));
     550                }
     551            }
     552        }
     553        return $m;
     554    }
     555       
    585556    // Get the maximum height of the titles for the bars
    586557    function GetMaxLabelHeight() {
    587         $m=10;
    588         if( $this->iObj != null ) {
    589             $n = count($this->iObj);
    590             // We can not include the title of GnttVLine since that title is stroked at the bottom
    591             // of the Gantt bar and not in the activity title columns
    592             for($i=0; $i < $n; ++$i) {
    593                 if( !empty($this->iObj[$i]->title) && !($this->iObj[$i] instanceof GanttVLine) ) {
    594                     $m=max($m,$this->iObj[$i]->title->GetHeight($this->img));
    595                 }
    596             }
    597         }
    598         return $m;
     558        $m=10;
     559        if( $this->iObj != null ) {
     560            $n = count($this->iObj);
     561            for($i=0; $i < $n; ++$i) {
     562                if( !empty($this->iObj[$i]->title) ) {
     563                    $m=max($m,$this->iObj[$i]->title->GetHeight($this->img));
     564                }
     565            }
     566        }
     567        return $m;
    599568    }
    600569
    601570    function GetMaxBarAbsHeight() {
    602         $m=0;
    603         if( $this->iObj != null ) {
    604             $m = $this->iObj[0]->GetAbsHeight($this->img);
    605             $n = count($this->iObj);
    606             for($i=1; $i < $n; ++$i) {
    607                 $m=max($m,$this->iObj[$i]->GetAbsHeight($this->img));
    608             }
    609         }
    610         return $m;
    611     }
    612 
     571        $m=0;
     572        if( $this->iObj != null ) {
     573            $m = $this->iObj[0]->GetAbsHeight($this->img);
     574            $n = count($this->iObj);
     575            for($i=1; $i < $n; ++$i) {
     576                $m=max($m,$this->iObj[$i]->GetAbsHeight($this->img));
     577            }
     578        }
     579        return $m;             
     580    }
     581       
    613582    // Get the maximum used line number (vertical position) for bars
    614583    function GetBarMaxLineNumber() {
    615         $m=1;
    616         if( $this->iObj != null ) {
    617             $m = $this->iObj[0]->GetLineNbr();
    618             $n = count($this->iObj);
    619             for($i=1; $i < $n; ++$i) {
    620                 $m=max($m,$this->iObj[$i]->GetLineNbr());
    621             }
    622         }
    623         return $m;
    624     }
    625 
     584        $m=1;
     585        if( $this->iObj != null ) {
     586            $m = $this->iObj[0]->GetLineNbr();
     587            $n = count($this->iObj);
     588            for($i=1; $i < $n; ++$i) {
     589                $m=max($m,$this->iObj[$i]->GetLineNbr());
     590            }
     591        }
     592        return $m;
     593    }
     594       
    626595    // Get the minumum and maximum used dates for all bars
    627596    function GetBarMinMax() {
    628         $start = 0 ;
    629         $n = count($this->iObj);
    630         while( $start < $n && $this->iObj[$start]->GetMaxDate() === false )
    631         ++$start;
    632         if( $start >= $n ) {
    633             JpgraphError::RaiseL(6006);
    634             //('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]');
    635         }
    636 
    637         $max=$this->scale->NormalizeDate($this->iObj[$start]->GetMaxDate());
    638         $min=$this->scale->NormalizeDate($this->iObj[$start]->GetMinDate());
    639 
    640         for($i=$start+1; $i < $n; ++$i) {
    641             $rmax = $this->scale->NormalizeDate($this->iObj[$i]->GetMaxDate());
    642             if( $rmax != false )
    643             $max=Max($max,$rmax);
    644             $rmin = $this->scale->NormalizeDate($this->iObj[$i]->GetMinDate());
    645             if( $rmin != false )
    646             $min=Min($min,$rmin);
    647         }
    648         $minDate = date("Y-m-d",$min);
    649         $min = strtotime($minDate);
    650         $maxDate = date("Y-m-d 23:59",$max);
    651         $max = strtotime($maxDate);
    652         return array($min,$max);
     597        $start = 0 ;
     598        $n = count($this->iObj);
     599        while( $start < $n && $this->iObj[$start]->GetMaxDate() === false )
     600            ++$start;
     601        if( $start >= $n ) {
     602            JpgraphError::RaiseL(6006);
     603//('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]');
     604        }
     605
     606        $max=$this->scale->NormalizeDate($this->iObj[$start]->GetMaxDate());
     607        $min=$this->scale->NormalizeDate($this->iObj[$start]->GetMinDate());
     608
     609        for($i=$start+1; $i < $n; ++$i) {
     610            $rmax = $this->scale->NormalizeDate($this->iObj[$i]->GetMaxDate());
     611            if( $rmax != false )
     612                $max=Max($max,$rmax);
     613            $rmin = $this->scale->NormalizeDate($this->iObj[$i]->GetMinDate());
     614            if( $rmin != false )
     615                $min=Min($min,$rmin);
     616        }
     617        $minDate = date("Y-m-d",$min);
     618        $min = strtotime($minDate);
     619        $maxDate = date("Y-m-d 23:59",$max);
     620        $max = strtotime($maxDate);     
     621        return array($min,$max);
    653622    }
    654623
     
    659628    function AutoSize() {
    660629
    661         if( $this->img->img == null ) {
    662             // The predefined left, right, top, bottom margins.
    663             // Note that the top margin might incease depending on
    664             // the title.
    665            $hadj = $vadj = 0;
    666            if( $this->doshadow ) {
    667                         $hadj = $this->shadow_width;
    668                 $vadj = $this->shadow_width+5;
    669             }
    670 
    671             $lm = $this->img->left_margin;
    672             $rm = $this->img->right_margin +$hadj;
    673             $rm += 2 ;
    674             $tm = $this->img->top_margin;
    675             $bm = $this->img->bottom_margin + $vadj;
    676             $bm += 2;
    677 
    678             // If there are any added GanttVLine we must make sure that the
    679             // bottom margin is wide enough to hold a title.
    680             $n = count($this->iObj);
    681                 for($i=0; $i < $n; ++$i) {
    682                 if( $this->iObj[$i] instanceof GanttVLine ) {
    683                                         $bm = max($bm,$this->iObj[$i]->title->GetHeight($this->img)+10);
    684                 }
    685                 }
    686 
    687             // First find out the height
    688             $n=$this->GetBarMaxLineNumber()+1;
    689             $m=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight());
    690             $height=$n*((1+$this->iLabelVMarginFactor)*$m);
    691 
    692             // Add the height of the scale titles
    693             $h=$this->scale->GetHeaderHeight();
    694             $height += $h;
    695 
    696             // Calculate the top margin needed for title and subtitle
    697             if( $this->title->t != "" ) {
    698                 $tm += $this->title->GetFontHeight($this->img);
    699             }
    700             if( $this->subtitle->t != "" ) {
    701                 $tm += $this->subtitle->GetFontHeight($this->img);
    702             }
    703 
    704             // ...and then take the bottom and top plot margins into account
    705             $height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin;
    706             // Now find the minimum width for the chart required
    707 
    708             // If day scale or smaller is shown then we use the day font width
    709             // as the base size unit.
    710             // If only weeks or above is displayed we use a modified unit to
    711             // get a smaller image.
    712             if( $this->scale->IsDisplayHour() || $this->scale->IsDisplayMinute() ) {
    713                 // Add 2 pixel margin on each side
    714                 $fw=$this->scale->day->GetFontWidth($this->img)+4;
    715             }
    716             elseif( $this->scale->IsDisplayWeek() ) {
    717                 $fw = 8;
    718             }
    719             elseif( $this->scale->IsDisplayMonth() ) {
    720                 $fw = 4;
    721             }
    722             else {
    723                 $fw = 2;
    724             }
    725 
    726             $nd=$this->scale->GetNumberOfDays();
    727 
    728             if( $this->scale->IsDisplayDay() ) {
    729                 // If the days are displayed we also need to figure out
    730                 // how much space each day's title will require.
    731                 switch( $this->scale->day->iStyle ) {
    732                     case DAYSTYLE_LONG :
    733                         $txt = "Monday";
    734                         break;
    735                     case DAYSTYLE_LONGDAYDATE1 :
    736                         $txt =  "Monday 23 Jun";
    737                         break;
    738                     case DAYSTYLE_LONGDAYDATE2 :
    739                         $txt =  "Monday 23 Jun 2003";
    740                         break;
    741                     case DAYSTYLE_SHORT :
    742                         $txt =  "Mon";
    743                         break;
    744                     case DAYSTYLE_SHORTDAYDATE1 :
     630        if( $this->img->img == null ) {
     631            // The predefined left, right, top, bottom margins.
     632            // Note that the top margin might incease depending on
     633            // the title.
     634            $lm = $this->img->left_margin;
     635            $rm = $this->img->right_margin;
     636            $rm += 2 ;
     637            $tm = $this->img->top_margin;
     638            $bm = $this->img->bottom_margin;
     639            $bm += 1;
     640            if( BRAND_TIMING ) $bm += 10;
     641                       
     642            // First find out the height                       
     643            $n=$this->GetBarMaxLineNumber()+1;
     644            $m=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight());
     645            $height=$n*((1+$this->iLabelVMarginFactor)*$m);                     
     646                       
     647            // Add the height of the scale titles                       
     648            $h=$this->scale->GetHeaderHeight();
     649            $height += $h;
     650
     651            // Calculate the top margin needed for title and subtitle
     652            if( $this->title->t != "" ) {
     653                $tm += $this->title->GetFontHeight($this->img);
     654            }
     655            if( $this->subtitle->t != "" ) {
     656                $tm += $this->subtitle->GetFontHeight($this->img);
     657            }
     658
     659            // ...and then take the bottom and top plot margins into account
     660            $height += $tm + $bm + $this->scale->iTopPlotMargin + $this->scale->iBottomPlotMargin;
     661            // Now find the minimum width for the chart required
     662
     663            // If day scale or smaller is shown then we use the day font width
     664            // as the base size unit.
     665            // If only weeks or above is displayed we use a modified unit to
     666            // get a smaller image.
     667            if( $this->scale->IsDisplayHour() || $this->scale->IsDisplayMinute() ) {
     668                // Add 2 pixel margin on each side
     669                $fw=$this->scale->day->GetFontWidth($this->img)+4;
     670            }
     671            elseif( $this->scale->IsDisplayWeek() ) {
     672                $fw = 8;
     673            }
     674            elseif( $this->scale->IsDisplayMonth() ) {
     675                $fw = 4;
     676            }
     677            else {
     678                $fw = 2;
     679            }
     680
     681            $nd=$this->scale->GetNumberOfDays();
     682
     683            if( $this->scale->IsDisplayDay() ) {
     684                // If the days are displayed we also need to figure out
     685                // how much space each day's title will require.
     686                switch( $this->scale->day->iStyle ) {
     687                    case DAYSTYLE_LONG :
     688                        $txt = "Monday";
     689                        break;
     690                    case DAYSTYLE_LONGDAYDATE1 :
     691                        $txt =  "Monday 23 Jun";
     692                        break;
     693                    case DAYSTYLE_LONGDAYDATE2 :
     694                        $txt =  "Monday 23 Jun 2003";
     695                        break;
     696                    case DAYSTYLE_SHORT :
     697                        $txt =  "Mon";
     698                        break;
     699                    case DAYSTYLE_SHORTDAYDATE1 :
    745700                        $txt =  "Mon 23/6";
    746                         break;
    747                     case DAYSTYLE_SHORTDAYDATE2 :
    748                         $txt =  "Mon 23 Jun";
    749                         break;
    750                     case DAYSTYLE_SHORTDAYDATE3 :
    751                         $txt =  "Mon 23";
    752                         break;
    753                     case DAYSTYLE_SHORTDATE1 :
     701                        break;
     702                    case DAYSTYLE_SHORTDAYDATE2 :
     703                        $txt =  "Mon 23 Jun";
     704                        break;
     705                    case DAYSTYLE_SHORTDAYDATE3 :
     706                        $txt =  "Mon 23";
     707                        break;
     708                    case DAYSTYLE_SHORTDATE1 :
    754709                        $txt =  "23/6";
    755                         break;
    756                     case DAYSTYLE_SHORTDATE2 :
    757                         $txt =  "23 Jun";
    758                         break;
    759                     case DAYSTYLE_SHORTDATE3 :
    760                         $txt =  "Mon 23";
    761                         break;
    762                     case DAYSTYLE_SHORTDATE4 :
    763                         $txt =  "88";
    764                         break;
    765                     case DAYSTYLE_CUSTOM :
    766                         $txt = date($this->scale->day->iLabelFormStr,strtotime('2003-12-20 18:00'));
    767                         break;
    768                     case DAYSTYLE_ONELETTER :
    769                     default:
    770                         $txt = "M";
    771                         break;
    772                 }
    773                 $fw = $this->scale->day->GetStrWidth($this->img,$txt)+6;
    774             }
    775 
    776             // If we have hours enabled we must make sure that each day has enough
    777             // space to fit the number of hours to be displayed.
    778             if( $this->scale->IsDisplayHour() ) {
    779                 // Depending on what format the user has choose we need different amount
    780                 // of space. We therefore create a typical string for the choosen format
    781                 // and determine the length of that string.
    782                 switch( $this->scale->hour->iStyle ) {
    783                     case HOURSTYLE_HMAMPM:
    784                         $txt = '12:00pm';
    785                         break;
    786                     case HOURSTYLE_H24:
    787                         // 13
    788                         $txt = '24';
    789                         break;
    790                     case HOURSTYLE_HAMPM:
    791                         $txt = '12pm';
    792                         break;
    793                     case HOURSTYLE_CUSTOM:
    794                         $txt = date($this->scale->hour->iLabelFormStr,strtotime('2003-12-20 18:00'));
    795                         break;
    796                     case HOURSTYLE_HM24:
    797                     default:
    798                         $txt = '24:00';
    799                         break;
    800                 }
    801 
    802                 $hfw = $this->scale->hour->GetStrWidth($this->img,$txt)+6;
    803                 $mw = $hfw;
    804                 if( $this->scale->IsDisplayMinute() ) {
    805                     // Depending on what format the user has choose we need different amount
    806                     // of space. We therefore create a typical string for the choosen format
    807                     // and determine the length of that string.
    808                     switch( $this->scale->minute->iStyle ) {
    809                         case HOURSTYLE_CUSTOM:
    810                             $txt2 = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55'));
    811                             break;
    812                         case MINUTESTYLE_MM:
    813                         default:
    814                             $txt2 = '15';
    815                             break;
    816                     }
    817 
    818                     $mfw = $this->scale->minute->GetStrWidth($this->img,$txt2)+6;
    819                     $n2 = ceil(60 / $this->scale->minute->GetIntervall() );
    820                     $mw = $n2 * $mfw;
    821                 }
    822                 $hfw = $hfw < $mw ? $mw : $hfw ;
    823                 $n = ceil(24*60 / $this->scale->TimeToMinutes($this->scale->hour->GetIntervall()) );
    824                 $hw = $n * $hfw;
    825                 $fw = $fw < $hw ? $hw : $fw ;
    826             }
    827 
    828             // We need to repeat this code block here as well.
    829             // THIS iS NOT A MISTAKE !
    830             // We really need it since we need to adjust for minutes both in the case
    831             // where hour scale is shown and when it is not shown.
    832 
    833             if( $this->scale->IsDisplayMinute() ) {
    834                 // Depending on what format the user has choose we need different amount
    835                 // of space. We therefore create a typical string for the choosen format
    836                 // and determine the length of that string.
    837                 switch( $this->scale->minute->iStyle ) {
    838                     case HOURSTYLE_CUSTOM:
    839                         $txt = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55'));
    840                         break;
    841                     case MINUTESTYLE_MM:
    842                     default:
    843                         $txt = '15';
    844                         break;
    845                 }
    846 
    847                 $mfw = $this->scale->minute->GetStrWidth($this->img,$txt)+6;
    848                 $n = ceil(60 / $this->scale->TimeToMinutes($this->scale->minute->GetIntervall()) );
    849                 $mw = $n * $mfw;
    850                 $fw = $fw < $mw ? $mw : $fw ;
    851             }
    852 
    853             // If we display week we must make sure that 7*$fw is enough
    854             // to fit up to 10 characters of the week font (if the week is enabled)
    855             if( $this->scale->IsDisplayWeek() ) {
    856                 // Depending on what format the user has choose we need different amount
    857                 // of space
    858                 $fsw = strlen($this->scale->week->iLabelFormStr);
    859                 if( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
    860                     $fsw += 8;
    861                 }
    862                 elseif( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) {
    863                     $fsw += 7;
    864                 }
    865                 else {
    866                     $fsw += 4;
    867                 }
    868 
    869                 $ww = $fsw*$this->scale->week->GetFontWidth($this->img);
    870                 if( 7*$fw < $ww ) {
    871                     $fw = ceil($ww/7);
    872                 }
    873             }
    874 
    875             if( !$this->scale->IsDisplayDay() && !$this->scale->IsDisplayHour() &&
    876                 !( ($this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ||
    877                         $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR) && $this->scale->IsDisplayWeek() ) ) {
    878                 // If we don't display the individual days we can shrink the
    879                 // scale a little bit. This is a little bit pragmatic at the
    880                 // moment and should be re-written to take into account
    881                 // a) What scales exactly are shown and
    882                 // b) what format do they use so we know how wide we need to
    883                 // make each scale text space at minimum.
    884                 $fw /= 2;
    885                 if( !$this->scale->IsDisplayWeek() ) {
    886                     $fw /= 1.8;
    887                 }
    888             }
    889 
    890             $cw = $this->GetMaxActInfoColWidth() ;
    891             $this->scale->actinfo->SetMinColWidth($cw);
    892             if( $this->img->width <= 0 ) {
    893                 // Now determine the width for the activity titles column
    894 
    895                 // Firdst find out the maximum width of each object column
    896                 $titlewidth = max(max($this->GetMaxLabelWidth(),
    897                 $this->scale->tableTitle->GetWidth($this->img)),
    898                 $this->scale->actinfo->GetWidth($this->img));
    899 
    900                 // Add the width of the vertivcal divider line
    901                 $titlewidth += $this->scale->divider->iWeight*2;
    902 
    903                                 // Adjust the width by the user specified zoom factor
    904                                 $fw *= $this->iZoomFactor;
    905 
    906                 // Now get the total width taking
    907                 // titlewidth, left and rigt margin, dayfont size
    908                 // into account
    909                 $width = $titlewidth + $nd*$fw + $lm+$rm;
    910             }
    911             else {
    912                 $width = $this->img->width;
    913             }
    914 
    915             $width = round($width);
    916             $height = round($height);
    917             // Make a sanity check on image size
    918             if( $width > MAX_GANTTIMG_SIZE_W || $height > MAX_GANTTIMG_SIZE_H ) {
    919                 JpgraphError::RaiseL(6007,$width,$height);
    920                 //("Sanity check for automatic Gantt chart size failed. Either the width (=$width) or height (=$height) is larger than MAX_GANTTIMG_SIZE. This could potentially be caused by a wrong date in one of the activities.");
    921             }
    922             $this->img->CreateImgCanvas($width,$height);
    923             $this->img->SetMargin($lm,$rm,$tm,$bm);
    924         }
     710                        break;
     711                    case DAYSTYLE_SHORTDATE2 :
     712                        $txt =  "23 Jun";
     713                        break;
     714                    case DAYSTYLE_SHORTDATE3 :
     715                        $txt =  "Mon 23";
     716                        break;
     717                    case DAYSTYLE_SHORTDATE4 :
     718                        $txt =  "88";
     719                        break;
     720                    case DAYSTYLE_CUSTOM :
     721                        $txt = date($this->scale->day->iLabelFormStr,
     722                                    strtotime('2003-12-20 18:00'));
     723                        break;
     724                    case DAYSTYLE_ONELETTER :
     725                    default:
     726                        $txt = "M";
     727                        break;
     728                }
     729                $fw = $this->scale->day->GetStrWidth($this->img,$txt)+6;
     730            }
     731
     732            // If we have hours enabled we must make sure that each day has enough
     733            // space to fit the number of hours to be displayed.
     734            if( $this->scale->IsDisplayHour() ) {
     735                // Depending on what format the user has choose we need different amount
     736                // of space. We therefore create a typical string for the choosen format
     737                // and determine the length of that string.
     738                switch( $this->scale->hour->iStyle ) {
     739                    case HOURSTYLE_HMAMPM:
     740                        $txt = '12:00pm';
     741                        break;
     742                    case HOURSTYLE_H24:
     743                        // 13
     744                        $txt = '24';
     745                        break;
     746                    case HOURSTYLE_HAMPM:
     747                        $txt = '12pm';
     748                        break;
     749                    case HOURSTYLE_CUSTOM:
     750                        $txt = date($this->scale->hour->iLabelFormStr,strtotime('2003-12-20 18:00'));
     751                        break;
     752                    case HOURSTYLE_HM24:
     753                    default:
     754                        $txt = '24:00';
     755                        break;
     756                }
     757
     758                $hfw = $this->scale->hour->GetStrWidth($this->img,$txt)+6;
     759                $mw = $hfw;
     760                if( $this->scale->IsDisplayMinute() ) {
     761                    // Depending on what format the user has choose we need different amount
     762                    // of space. We therefore create a typical string for the choosen format
     763                    // and determine the length of that string.
     764                    switch( $this->scale->minute->iStyle ) {
     765                        case HOURSTYLE_CUSTOM:
     766                            $txt2 = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55'));
     767                            break;
     768                        case MINUTESTYLE_MM:
     769                        default:
     770                            $txt2 = '15';
     771                            break;
     772                    }
     773                   
     774                    $mfw = $this->scale->minute->GetStrWidth($this->img,$txt2)+6;
     775                    $n2 = ceil(60 / $this->scale->minute->GetIntervall() );
     776                    $mw = $n2 * $mfw;
     777                }
     778                $hfw = $hfw < $mw ? $mw : $hfw ;   
     779                $n = ceil(24*60 / $this->scale->TimeToMinutes($this->scale->hour->GetIntervall()) );
     780                $hw = $n * $hfw;
     781                $fw = $fw < $hw ? $hw : $fw ;
     782            }
     783
     784            // We need to repeat this code block here as well.
     785            // THIS iS NOT A MISTAKE !
     786            // We really need it since we need to adjust for minutes both in the case
     787            // where hour scale is shown and when it is not shown.
     788
     789            if( $this->scale->IsDisplayMinute() ) {
     790                // Depending on what format the user has choose we need different amount
     791                // of space. We therefore create a typical string for the choosen format
     792                // and determine the length of that string.
     793                switch( $this->scale->minute->iStyle ) {
     794                    case HOURSTYLE_CUSTOM:
     795                        $txt = date($this->scale->minute->iLabelFormStr,strtotime('2005-05-15 18:55'));
     796                        break;
     797                    case MINUTESTYLE_MM:
     798                    default:
     799                        $txt = '15';
     800                        break;
     801                }
     802               
     803                $mfw = $this->scale->minute->GetStrWidth($this->img,$txt)+6;
     804                $n = ceil(60 / $this->scale->TimeToMinutes($this->scale->minute->GetIntervall()) );
     805                $mw = $n * $mfw;
     806                $fw = $fw < $mw ? $mw : $fw ;
     807            }
     808
     809            // If we display week we must make sure that 7*$fw is enough
     810            // to fit up to 10 characters of the week font (if the week is enabled)
     811            if( $this->scale->IsDisplayWeek() ) {
     812                // Depending on what format the user has choose we need different amount
     813                // of space
     814                $fsw = strlen($this->scale->week->iLabelFormStr);
     815                if( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
     816                    $fsw += 8;
     817                }
     818                elseif( $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ) {
     819                    $fsw += 7;
     820                }
     821                else {
     822                    $fsw += 4;
     823                }
     824                   
     825                $ww = $fsw*$this->scale->week->GetFontWidth($this->img);
     826                if( 7*$fw < $ww ) {
     827                    $fw = ceil($ww/7);
     828                }
     829            }
     830
     831            if( !$this->scale->IsDisplayDay() && !$this->scale->IsDisplayHour() &&
     832                !( ($this->scale->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ||
     833                    $this->scale->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR) && $this->scale->IsDisplayWeek() ) ) {
     834                // If we don't display the individual days we can shrink the
     835                // scale a little bit. This is a little bit pragmatic at the
     836                // moment and should be re-written to take into account
     837                // a) What scales exactly are shown and
     838                // b) what format do they use so we know how wide we need to
     839                // make each scale text space at minimum.
     840                $fw /= 2;
     841                if( !$this->scale->IsDisplayWeek() ) {
     842                    $fw /= 1.8;
     843                }
     844            }
     845
     846            $cw = $this->GetMaxActInfoColWidth() ;
     847            $this->scale->actinfo->SetMinColWidth($cw);
     848            if( $this->img->width <= 0 ) {
     849                // Now determine the width for the activity titles column
     850
     851                // Firdst find out the maximum width of each object column
     852                $titlewidth = max(max($this->GetMaxLabelWidth(),
     853                                      $this->scale->tableTitle->GetWidth($this->img)),
     854                                  $this->scale->actinfo->GetWidth($this->img));
     855
     856                // Add the width of the vertivcal divider line
     857                $titlewidth += $this->scale->divider->iWeight*2;
     858
     859
     860                // Now get the total width taking
     861                // titlewidth, left and rigt margin, dayfont size
     862                // into account
     863                $width = $titlewidth + $nd*$fw + $lm+$rm;
     864            }
     865            else {
     866                $width = $this->img->width;
     867            }
     868
     869            $width = round($width);
     870            $height = round($height);
     871            // Make a sanity check on image size
     872            if( $width > MAX_GANTTIMG_SIZE_W || $height > MAX_GANTTIMG_SIZE_H ) {
     873                JpgraphError::RaiseL(6007,$width,$height);
     874//("Sanity check for automatic Gantt chart size failed. Either the width (=$width) or height (=$height) is larger than MAX_GANTTIMG_SIZE. This could potentially be caused by a wrong date in one of the activities.");
     875            }
     876            $this->img->CreateImgCanvas($width,$height);                       
     877            $this->img->SetMargin($lm,$rm,$tm,$bm);
     878        }
    925879    }
    926880
     
    930884    // must walk through all the objects, sigh...
    931885    function GetMaxActInfoColWidth() {
    932         $n = count($this->iObj);
    933         if( $n == 0 ) return;
    934         $w = array();
    935         $m = $this->scale->actinfo->iLeftColMargin + $this->scale->actinfo->iRightColMargin;
    936 
    937         for( $i=0; $i < $n; ++$i ) {
    938             $tmp = $this->iObj[$i]->title->GetColWidth($this->img,$m);
    939             $nn = count($tmp);
    940             for( $j=0; $j < $nn; ++$j ) {
    941                 if( empty($w[$j]) )
    942                 $w[$j] = $tmp[$j];
    943                 else
    944                 $w[$j] = max($w[$j],$tmp[$j]);
    945             }
    946         }
    947         return $w;
     886        $n = count($this->iObj);
     887        if( $n == 0 ) return;
     888        $w = array();
     889        $m = $this->scale->actinfo->iLeftColMargin + $this->scale->actinfo->iRightColMargin;
     890       
     891        for( $i=0; $i < $n; ++$i ) {
     892            $tmp = $this->iObj[$i]->title->GetColWidth($this->img,$m);
     893            $nn = count($tmp);
     894            for( $j=0; $j < $nn; ++$j ) {
     895                if( empty($w[$j]) )
     896                    $w[$j] = $tmp[$j];
     897                else
     898                    $w[$j] = max($w[$j],$tmp[$j]);
     899            }
     900        }
     901        return $w;
    948902    }
    949903
    950904    // Stroke the gantt chart
    951     function Stroke($aStrokeFileName="") {
    952 
    953         // If the filename is the predefined value = '_csim_special_'
    954         // we assume that the call to stroke only needs to do enough
    955         // to correctly generate the CSIM maps.
    956         // We use this variable to skip things we don't strictly need
    957         // to do to generate the image map to improve performance
    958         // a best we can. Therefor you will see a lot of tests !$_csim in the
    959         // code below.
    960         $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
    961 
    962         // Should we autoscale dates?
    963 
    964         if( !$this->scale->IsRangeSet() ) {
    965             list($min,$max) = $this->GetBarMinMax();
    966             $this->scale->SetRange($min,$max);
    967         }
    968 
    969         $this->scale->AdjustStartEndDay();
    970 
    971         // Check if we should autoscale the image
    972         $this->AutoSize();
    973 
    974         // Should we start from the top or just spread the bars out even over the
    975         // available height
    976         $this->scale->SetVertLayout($this->iLayout);
    977         if( $this->iLayout == GANTT_FROMTOP ) {
    978             $maxheight=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight());
    979             $this->scale->SetVertSpacing($maxheight*(1+$this->iLabelVMarginFactor));
    980         }
    981         // If it hasn't been set find out the maximum line number
    982         if( $this->scale->iVertLines == -1 )
    983                 $this->scale->iVertLines = $this->GetBarMaxLineNumber()+1;
    984 
    985         $maxwidth=max($this->scale->actinfo->GetWidth($this->img),
    986         max($this->GetMaxLabelWidth(),
    987         $this->scale->tableTitle->GetWidth($this->img)));
    988 
    989         $this->scale->SetLabelWidth($maxwidth+$this->scale->divider->iWeight);//*(1+$this->iLabelHMarginFactor));
    990 
    991         if( !$_csim ) {
    992             $this->StrokePlotArea();
    993             if( $this->iIconDepth == DEPTH_BACK ) {
    994                 $this->StrokeIcons();
    995             }
    996         }
    997 
    998         $this->scale->Stroke();
    999 
    1000         if( !$_csim ) {
    1001             // Due to a minor off by 1 bug we need to temporarily adjust the margin
    1002             $this->img->right_margin--;
    1003             $this->StrokePlotBox();
    1004             $this->img->right_margin++;
    1005         }
    1006 
    1007         // Stroke Grid line
    1008         $this->hgrid->Stroke($this->img,$this->scale);
    1009 
    1010         $n = count($this->iObj);
    1011         for($i=0; $i < $n; ++$i) {
    1012             //$this->iObj[$i]->SetLabelLeftMargin(round($maxwidth*$this->iLabelHMarginFactor/2));
    1013             $this->iObj[$i]->Stroke($this->img,$this->scale);
    1014         }
    1015 
    1016         $this->StrokeTitles();
    1017 
    1018         if( !$_csim ) {
    1019             $this->StrokeConstrains();
    1020             $this->footer->Stroke($this->img);
    1021 
    1022 
    1023             if( $this->iIconDepth == DEPTH_FRONT) {
    1024                 $this->StrokeIcons();
    1025             }
    1026 
    1027             // Stroke all added user texts
    1028             $this->StrokeTexts();
    1029 
    1030             // Should we do any final image transformation
    1031             if( $this->iImgTrans ) {
    1032                 if( !class_exists('ImgTrans',false) ) {
    1033                     require_once('jpgraph_imgtrans.php');
    1034                 }
    1035 
    1036                 $tform = new ImgTrans($this->img->img);
    1037                 $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
    1038                 $this->iImgTransDirection,$this->iImgTransHighQ,
    1039                 $this->iImgTransMinSize,$this->iImgTransFillColor,
    1040                 $this->iImgTransBorder);
    1041             }
    1042 
    1043 
    1044             // If the filename is given as the special "__handle"
    1045             // then the image handler is returned and the image is NOT
    1046             // streamed back
    1047             if( $aStrokeFileName == _IMG_HANDLER ) {
    1048                 return $this->img->img;
    1049             }
    1050             else {
    1051                 // Finally stream the generated picture
    1052                 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
    1053                 $aStrokeFileName);
    1054             }
    1055         }
     905    function Stroke($aStrokeFileName="") {     
     906
     907        // If the filename is the predefined value = '_csim_special_'
     908        // we assume that the call to stroke only needs to do enough
     909        // to correctly generate the CSIM maps.
     910        // We use this variable to skip things we don't strictly need
     911        // to do to generate the image map to improve performance
     912        // a best we can. Therefor you will see a lot of tests !$_csim in the
     913        // code below.
     914        $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
     915
     916        // Should we autoscale dates?
     917
     918        if( !$this->scale->IsRangeSet() ) {
     919            list($min,$max) = $this->GetBarMinMax();
     920            $this->scale->SetRange($min,$max);
     921        }
     922
     923        $this->scale->AdjustStartEndDay();
     924
     925        // Check if we should autoscale the image
     926        $this->AutoSize();
     927
     928        // Should we start from the top or just spread the bars out even over the
     929        // available height
     930        $this->scale->SetVertLayout($this->iLayout);                   
     931        if( $this->iLayout == GANTT_FROMTOP ) {
     932            $maxheight=max($this->GetMaxLabelHeight(),$this->GetMaxBarAbsHeight());
     933            $this->scale->SetVertSpacing($maxheight*(1+$this->iLabelVMarginFactor));
     934        }
     935        // If it hasn't been set find out the maximum line number
     936        if( $this->scale->iVertLines == -1 )
     937            $this->scale->iVertLines = $this->GetBarMaxLineNumber()+1; 
     938               
     939        $maxwidth=max($this->scale->actinfo->GetWidth($this->img),
     940                      max($this->GetMaxLabelWidth(),
     941                      $this->scale->tableTitle->GetWidth($this->img)));
     942
     943        $this->scale->SetLabelWidth($maxwidth+$this->scale->divider->iWeight);//*(1+$this->iLabelHMarginFactor));
     944
     945        if( !$_csim ) {
     946            $this->StrokePlotArea();
     947            if( $this->iIconDepth == DEPTH_BACK ) {
     948                $this->StrokeIcons();
     949            }
     950        }
     951
     952        $this->scale->Stroke();
     953
     954        if( !$_csim ) {
     955            // Due to a minor off by 1 bug we need to temporarily adjust the margin
     956            $this->img->right_margin--;
     957            $this->StrokePlotBox();
     958            $this->img->right_margin++;
     959        }
     960
     961        // Stroke Grid line
     962        $this->hgrid->Stroke($this->img,$this->scale);
     963
     964        $n = count($this->iObj);
     965        for($i=0; $i < $n; ++$i) {
     966            //$this->iObj[$i]->SetLabelLeftMargin(round($maxwidth*$this->iLabelHMarginFactor/2));
     967            $this->iObj[$i]->Stroke($this->img,$this->scale);
     968        }
     969
     970        $this->StrokeTitles();
     971
     972        if( !$_csim ) {
     973            $this->StrokeConstrains();
     974            $this->footer->Stroke($this->img);
     975
     976
     977            if( $this->iIconDepth == DEPTH_FRONT) {
     978                $this->StrokeIcons();
     979            }
     980
     981            // Should we do any final image transformation
     982            if( $this->iImgTrans ) {
     983                if( !class_exists('ImgTrans',false) ) {
     984                    require_once('jpgraph_imgtrans.php');
     985                }
     986           
     987                $tform = new ImgTrans($this->img->img);
     988                $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
     989                                                 $this->iImgTransDirection,$this->iImgTransHighQ,
     990                                                 $this->iImgTransMinSize,$this->iImgTransFillColor,
     991                                                 $this->iImgTransBorder);
     992            }
     993           
     994           
     995            // If the filename is given as the special "__handle"
     996            // then the image handler is returned and the image is NOT
     997            // streamed back
     998            if( $aStrokeFileName == _IMG_HANDLER ) {
     999                return $this->img->img;
     1000            }
     1001            else {
     1002                // Finally stream the generated picture                                 
     1003                $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
     1004                                           $aStrokeFileName);           
     1005            }
     1006        }
    10561007    }
    10571008
    10581009    function StrokeConstrains() {
    1059         $n = count($this->iObj);
    1060 
    1061         // Stroke all constrains
    1062         for($i=0; $i < $n; ++$i) {
    1063 
    1064             // Some gantt objects may not have constraints associated with them
    1065             // for example we can add IconPlots which doesn't have this property.
    1066             if( empty($this->iObj[$i]->constraints) ) continue;
    1067 
    1068             $numConstrains = count($this->iObj[$i]->constraints);
    1069 
    1070             for( $k = 0; $k < $numConstrains; $k++ ) {
    1071                 $vpos = $this->iObj[$i]->constraints[$k]->iConstrainRow;
    1072                 if( $vpos >= 0 ) {
    1073                     $c1 = $this->iObj[$i]->iConstrainPos;
    1074 
    1075                     // Find out which object is on the target row
    1076                     $targetobj = -1;
    1077                     for( $j=0; $j < $n && $targetobj == -1; ++$j ) {
    1078                         if( $this->iObj[$j]->iVPos == $vpos ) {
    1079                             $targetobj = $j;
    1080                         }
    1081                     }
    1082                     if( $targetobj == -1 ) {
    1083                         JpGraphError::RaiseL(6008,$this->iObj[$i]->iVPos,$vpos);
    1084                         //('You have specifed a constrain from row='.$this->iObj[$i]->iVPos.' to row='.$vpos.' which does not have any activity.');
    1085                     }
    1086                     $c2 = $this->iObj[$targetobj]->iConstrainPos;
    1087                     if( count($c1) == 4 && count($c2 ) == 4) {
    1088                         switch( $this->iObj[$i]->constraints[$k]->iConstrainType ) {
    1089                             case CONSTRAIN_ENDSTART:
    1090                                 if( $c1[1] < $c2[1] ) {
    1091                                     $link = new GanttLink($c1[2],$c1[3],$c2[0],$c2[1]);
    1092                                 }
    1093                                 else {
    1094                                     $link = new GanttLink($c1[2],$c1[1],$c2[0],$c2[3]);
    1095                                 }
    1096                                 $link->SetPath(3);
    1097                                 break;
    1098                             case CONSTRAIN_STARTEND:
    1099                                 if( $c1[1] < $c2[1] ) {
    1100                                     $link = new GanttLink($c1[0],$c1[3],$c2[2],$c2[1]);
    1101                                 }
    1102                                 else {
    1103                                     $link = new GanttLink($c1[0],$c1[1],$c2[2],$c2[3]);
    1104                                 }
    1105                                 $link->SetPath(0);
    1106                                 break;
    1107                             case CONSTRAIN_ENDEND:
    1108                                 if( $c1[1] < $c2[1] ) {
    1109                                     $link = new GanttLink($c1[2],$c1[3],$c2[2],$c2[1]);
    1110                                 }
    1111                                 else {
    1112                                     $link = new GanttLink($c1[2],$c1[1],$c2[2],$c2[3]);
    1113                                 }
    1114                                 $link->SetPath(1);
    1115                                 break;
    1116                             case CONSTRAIN_STARTSTART:
    1117                                 if( $c1[1] < $c2[1] ) {
    1118                                     $link = new GanttLink($c1[0],$c1[3],$c2[0],$c2[1]);
    1119                                 }
    1120                                 else {
    1121                                     $link = new GanttLink($c1[0],$c1[1],$c2[0],$c2[3]);
    1122                                 }
    1123                                 $link->SetPath(3);
    1124                                 break;
    1125                             default:
    1126                                 JpGraphError::RaiseL(6009,$this->iObj[$i]->iVPos,$vpos);
    1127                                 //('Unknown constrain type specified from row='.$this->iObj[$i]->iVPos.' to row='.$vpos);
    1128                                 break;
    1129                         }
    1130 
    1131                         $link->SetColor($this->iObj[$i]->constraints[$k]->iConstrainColor);
    1132                         $link->SetArrow($this->iObj[$i]->constraints[$k]->iConstrainArrowSize,
    1133                         $this->iObj[$i]->constraints[$k]->iConstrainArrowType);
    1134 
    1135                         $link->Stroke($this->img);
    1136                     }
    1137                 }
    1138             }
    1139         }
     1010        $n = count($this->iObj);
     1011
     1012        // Stroke all constrains
     1013        for($i=0; $i < $n; ++$i) {
     1014
     1015            // Some gantt objects may not have constraints associated with them
     1016            // for example we can add IconPlots which doesn't have this property.
     1017            if( empty($this->iObj[$i]->constraints) ) continue;
     1018
     1019            $numConstrains = count($this->iObj[$i]->constraints);
     1020
     1021            for( $k = 0; $k < $numConstrains; $k++ ) {
     1022                $vpos = $this->iObj[$i]->constraints[$k]->iConstrainRow;
     1023                if( $vpos >= 0 ) {
     1024                    $c1 = $this->iObj[$i]->iConstrainPos;
     1025
     1026                    // Find out which object is on the target row
     1027                    $targetobj = -1;
     1028                    for( $j=0; $j < $n && $targetobj == -1; ++$j ) {
     1029                        if( $this->iObj[$j]->iVPos == $vpos ) {
     1030                            $targetobj = $j;
     1031                        }
     1032                    }
     1033                    if( $targetobj == -1 ) {
     1034                        JpGraphError::RaiseL(6008,$this->iObj[$i]->iVPos,$vpos);
     1035//('You have specifed a constrain from row='.$this->iObj[$i]->iVPos.' to row='.$vpos.' which does not have any activity.');
     1036                    }
     1037                    $c2 = $this->iObj[$targetobj]->iConstrainPos;
     1038                    if( count($c1) == 4 && count($c2 ) == 4) {
     1039                        switch( $this->iObj[$i]->constraints[$k]->iConstrainType ) {
     1040                            case CONSTRAIN_ENDSTART:
     1041                                if( $c1[1] < $c2[1] ) {
     1042                                    $link = new GanttLink($c1[2],$c1[3],$c2[0],$c2[1]);
     1043                                }
     1044                                else {
     1045                                    $link = new GanttLink($c1[2],$c1[1],$c2[0],$c2[3]);
     1046                                }
     1047                                $link->SetPath(3);
     1048                                break;
     1049                            case CONSTRAIN_STARTEND:
     1050                                if( $c1[1] < $c2[1] ) {
     1051                                    $link = new GanttLink($c1[0],$c1[3],$c2[2],$c2[1]);
     1052                                }
     1053                                else {
     1054                                    $link = new GanttLink($c1[0],$c1[1],$c2[2],$c2[3]);
     1055                                }
     1056                                $link->SetPath(0);
     1057                                break;
     1058                            case CONSTRAIN_ENDEND:
     1059                                if( $c1[1] < $c2[1] ) {
     1060                                    $link = new GanttLink($c1[2],$c1[3],$c2[2],$c2[1]);
     1061                                }
     1062                                else {
     1063                                    $link = new GanttLink($c1[2],$c1[1],$c2[2],$c2[3]);
     1064                                }
     1065                                $link->SetPath(1);
     1066                                break;
     1067                            case CONSTRAIN_STARTSTART:
     1068                                if( $c1[1] < $c2[1] ) {
     1069                                    $link = new GanttLink($c1[0],$c1[3],$c2[0],$c2[1]);
     1070                                }
     1071                                else {
     1072                                    $link = new GanttLink($c1[0],$c1[1],$c2[0],$c2[3]);
     1073                                }
     1074                                $link->SetPath(3);
     1075                                break;
     1076                            default:
     1077                                JpGraphError::RaiseL(6009,$this->iObj[$i]->iVPos,$vpos);
     1078//('Unknown constrain type specified from row='.$this->iObj[$i]->iVPos.' to row='.$vpos);
     1079                                break;
     1080                        }
     1081
     1082                        $link->SetColor($this->iObj[$i]->constraints[$k]->iConstrainColor);
     1083                        $link->SetArrow($this->iObj[$i]->constraints[$k]->iConstrainArrowSize,
     1084                                        $this->iObj[$i]->constraints[$k]->iConstrainArrowType);
     1085 
     1086                        $link->Stroke($this->img);
     1087                    }
     1088                }
     1089            }
     1090        }
    11401091    }
    11411092
    11421093    function GetCSIMAreas() {
    1143         if( !$this->iHasStroked )
    1144         $this->Stroke(_CSIM_SPECIALFILE);
    1145 
    1146         $csim = $this->title->GetCSIMAreas();
    1147         $csim .= $this->subtitle->GetCSIMAreas();
    1148         $csim .= $this->subsubtitle->GetCSIMAreas();
    1149 
    1150         $n = count($this->iObj);
    1151         for( $i=$n-1; $i >= 0; --$i )
    1152         $csim .= $this->iObj[$i]->GetCSIMArea();
    1153         return $csim;
     1094        if( !$this->iHasStroked )
     1095            $this->Stroke(_CSIM_SPECIALFILE);
     1096 
     1097        $csim = $this->title->GetCSIMAreas();
     1098        $csim .= $this->subtitle->GetCSIMAreas();
     1099        $csim .= $this->subsubtitle->GetCSIMAreas();
     1100
     1101        $n = count($this->iObj);
     1102        for( $i=$n-1; $i >= 0; --$i )
     1103            $csim .= $this->iObj[$i]->GetCSIMArea();
     1104        return $csim;
    11541105    }
    11551106}
     
    11771128
    11781129    function GetLen() {
    1179         return $this->iLen ;
     1130        return $this->iLen ;
    11801131    }
    11811132
    11821133    function GetImg($aIdx) {
    1183         if( $aIdx < 0 || $aIdx >= $this->iLen ) {
    1184             JpGraphError::RaiseL(6010,$aIdx);
    1185             //('Illegal icon index for Gantt builtin icon ['.$aIdx.']');
    1186         }
    1187         return Image::CreateFromString(base64_decode($this->iBuiltinIcon[$aIdx][1]));
    1188     }
    1189 
    1190     function __construct() {
    1191         //==========================================================
    1192         // warning.png
    1193         //==========================================================
    1194         $this->iBuiltinIcon[0][0]= 1043 ;
    1195         $this->iBuiltinIcon[0][1]=
    1196      'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
    1197      'B3RJTUUH0wgKFSgilWPhUQAAA6BJREFUeNrtl91rHFUYh5/3zMx+Z5JNUoOamCZNaqTZ6IWIkqRiQWmi1IDetHfeiCiltgXBP8AL'.
    1198      '0SIUxf/AvfRSBS9EKILFFqyIH9CEmFZtPqrBJLs7c+b1YneT3WTTbNsUFPLCcAbmzPt73o9zzgzs2Z793231UOdv3w9k9Z2uzOdA'.
    1199      '5+2+79yNeL7Hl7hw7oeixRMZ6PJM26W18DNAm/Vh7lR8fqh97NmMF11es1iFpMATqdirwMNA/J4DpIzkr5YsAF1PO6gIMYHRdPwl'.
    1200      'oO2elmB+qH3sm7XozbkgYvy8SzYnZPtcblyM6I+5z3jQ+0vJfgpEu56BfI9vUkbyi2HZd1QJoeWRiAjBd4SDCW8SSAOy6wBHMzF7'.
    1201      'YdV2A+ROuvRPLfHoiSU0EMY/cDAIhxJeGngKaN1VgHyPL7NBxI1K9P4QxBzw3K1zJ/zkG8B9uwaQ7/HNsRZv9kohBGD0o7JqMYS/'.
    1202      '/ynPidQw/LrBiPBcS/yFCT95DvB2BWAy4575PaQbQKW+tPd3GCItu2odKI++YxiKu0d26oWmAD7paZU/rLz37VqIijD2YbnzNBBE'.
    1203      'IBHf8K8qjL7vYhCGErEU8CTg3xXAeMp96GrJEqkyXkm9Bhui1xfsunjdGhcYLq+IzjsGmBt5YH/cmJkFq6gIqlon3u4LxdKGuCIo'.
    1204      'Qu41g0E41po+2R33Xt5uz9kRIB2UTle7PnfKrROP1HD4sRjZlq0lzhwoZ6rDNeTi3nEg1si/7FT7kYQbXS6E5E65tA5uRF9tutq0'.
    1205      'K/VwAF+/FbIYWt6+tjQM/AqUms7A4Wy6d7YSfSNxgMmzi0ycWWworio4QJvj4LpuL5BqugTnXzzqJsJwurrlNhJXFaavW67NRw3F'.
    1206      'q+aJcCQVe9fzvJGmAY7/dPH0gi0f64OveGxa+usCuQMeZ0+kt8BVrX+qPO9Bzx0MgqBvs+a2PfDdYIf+WAjXU1ub4tqNaPPzRs8A'.
    1207      'blrli+WVn79cXn0cWKl+tGx7HLc7pu3CSmnfitL+l1UihAhwjFkPQev4K/fSABjBM8JCaFuurJU+rgW41SroA8aNMVNAFtgHJCsn'.
    1208      'XGy/58QVxAC9MccJtZ5kIzNlW440WrJ2ea4YPA9cAooA7i0A/gS+iqLoOpB1HOegqrYB3UBmJrAtQAJwpwPr1Ry92wVlgZsiYlW1'.
    1209      'uX1gU36dymgqYxJIJJNJT1W9QqHgNwFQBGYqo94OwHZQUuPD7ACglSvc+5n5T9m/wfJJX4U9qzEAAAAASUVORK5CYII=' ;
    1210 
    1211         //==========================================================
    1212         // edit.png
    1213         //==========================================================
    1214         $this->iBuiltinIcon[1][0]= 959 ;
    1215         $this->iBuiltinIcon[1][1]=
    1216      'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAFgAWABY9j+ZuwAAAAlwSFlz'.
    1217      'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDAwbIEXOA6AAAAM8SURBVHicpdRPaBxlHMbx76ZvsmOTmm1dsEqQSIIsEmGVBAQjivEQ'.
    1218      'PAUJngpWsAWlBw8egpQepKwplN4ULEG9CjkEyUFKlSJrWTG0IU51pCsdYW2ncUPjdtp9Z+f3vuNhu8nKbmhaf5cZeGc+PO8zf1Lc'.
    1219      'm0KhkACICCKCMeaBjiLC0tLSnjNvPmuOHRpH0TZTU1M8zBi9wakzn7OFTs5sw8YYACYmJrre7HkeuVyu69qPF77hlT1XmZ0eQ03O'.
    1220      'wOLJTvhBx1rLz18VmJ0eY+jVd2FxDkKXnvYLHgb97OgLzE4ON9Hzc1B1QaQzsed5O0Lta3Ec89OnR5h5McfQ+Mw2qgQUnfBOPbZ3'.
    1221      'bK3l+xOvMT0+3ERLp5FNF6UEjcL32+DdVmGt5WLhDYYPZrbRqreFumXwql0S3w9tnDvLWD5PZigPpdOwuYpSCo3C8wU3UHxQdHbf'.
    1222      'cZIkNM6dxcnlUM4k1eUFMlUPpUADbpkttFarHe6oYqeOr6yt4RzMQHYUcUsQVtGicHDwKprViuLDkkOtVnsHCHZVRVy/zcj1i5Af'.
    1223      'h8AjdIts+hUcGcYPK3iBtKM3gD/uAzf/AdY2mmmVgy6X8YNNKmGIvyloPcB8SUin07RQ4EZHFdsdG0wkJEnEaHAJxvKEpSLeaokV'.
    1224      'r4zWmhUZYLlY4b1D03y5eIEWCtS7vsciAgiIxkQRabWOrlQor66y4pUphoJb1jiO4uO5o0S3q6RSqVbiOmC7VCEgAhLSaDQ48dH7'.
    1225      'vD46REY0iysegSjKQciRt99ib7qXwX0O+pG4teM6YKHLB9JMq4mTmF9/+AKA4wvLZByH7OgYL7+UY2qvw/7Bfg5kHiXjJFyv3CGO'.
    1226      'Y1rof+BW4t/XLiPG0DCGr79d4XzRxRnIMn98huXSTYyJ6et1UNYQhRvcinpJq86H3wGPPPM0iBDd+QffD1g4eZjLvuG7S1Wef26E'.
    1227      'J7L7eSx7gAHVg7V3MSbi6m/r93baBd6qQjerAJg/9Ql/XrvG0ON1+vv7GH3qSfY5fahUnSTpwZgIEQesaVXRPbHRG/xyJSAxMYlp'.
    1228      'EOm71HUINiY7mGb95l/8jZCyQmJjMDGJjUmsdCROtZ0n/P/Z8v4Fs2MTUUf7vYoAAAAASUVORK5CYII=' ;
    1229 
    1230         //==========================================================
    1231         // endconstrain.png
    1232         //==========================================================
    1233         $this->iBuiltinIcon[2][0]= 666 ;
    1234         $this->iBuiltinIcon[2][1]=
    1235      'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
    1236      'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ALEREILkh0+eQAAAIXSURBVHictZU9aFNRFMd/N81HX77aptJUWmp1LHRpIcWhg5sIDlUQ'.
    1237      'LAXB4t7RRUpwEhy7iQ46CCIoSHcl0CFaoVARU2MFMYktadLXJNok7x2HtCExvuYFmnO4w/3gx+Gc/z1HKRTdMEdXqHbB/sgc/sic'.
    1238      'nDoYAI8XwDa8o1RMLT+2hAsigtTvbIGVqhX46szUifBGswUeCPgAGB7QeLk0X4Ork+HOxo1VgSqGASjMqkn8W4r4vVtEgI/RRQEL'.
    1239      'vaoGD85cl5V3nySR/S1mxWxab7f35PnntNyMJeRr9kCMqiHTy09EoeToLwggx6ymiMOD/VwcD7Oa/MHkcIiQx026WGYto5P/U+ZZ'.
    1240      '7gD0QwDuT5z9N3LrVPi0Xs543eQPKkRzaS54eviJIp4tMFQFMllAWN2qcRZHBnixNM8NYD162xq8u7ePSQ+GX2Pjwxc2dB2cLtB8'.
    1241      '7GgamCb0anBYBeChMtl8855CarclxU1gvViiUK4w2OMkNDnGeJ8bt9fH90yOnOkCwLFTwhzykhvtYzOWoBBbY//R3dbaNTYhf2RO'.
    1242      'QpeuUMzv188MlwuHy0H13HnE48UzMcL0WAtUHX8OxZHoG1URiFw7rnLLCswuSPD1ulze/iWjT2PSf+dBXRFtVVGIvzqph0pQL7VE'.
    1243      'avXYaXXxPwsnt0imdttCocMmZBdK7YU9D8wuNOW0nXc6QWzPsSa5naZ1beb9BbGB6dxGtMnXAAAAAElFTkSuQmCC' ;
    1244 
    1245         //==========================================================
    1246         // mail.png
    1247         //==========================================================
    1248         $this->iBuiltinIcon[3][0]= 1122 ;
    1249         $this->iBuiltinIcon[3][1]=
    1250      'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
    1251      'AAALEAAACxABrSO9dQAAAAd0SU1FB9AJHAMfFvL9OU8AAAPfSURBVHictZRdaBRXFMd/987H7tbNx8aYtGCrEexDsOBDaKHFxirb'.
    1252      'h0qhsiY0ykppKq1osI99C4H2WSiFFMHWUhXBrjRi0uCmtSEUGgP1QWqhWjGkoW7M1kTX3WRn5p4+TJJNGolQ6IXDnDtz+N0z/3PP'.
    1253      'UWBIpdpYa23b9g09PZ2kUrOrvmUyGVKp1Ao/mUyi56YnVgWfO/P1CihAd/dJMpmaNROIRq8BkM1m0bH6TasC3j6QXgFdXI+DR6PR'.
    1254      'JX/Pno8B+KLnMKqlpUU8z8MYs2RBEDzWf9J+0RcRbMdxGBsbw/fmCXwPMUEYID4iAVp8wIRmDIHMo4yHSIBSASKC+CWE0C/PF9jU'.
    1255      '3B6Cp+4M07C5FUtKGNvGwQJctPgIsgD2wRhEIqAMGB+UQYkHJgYYZD7P1HwVlmWhHcfhyk83KeRGUW4t6CgoG5SNUS4KBWgQDUov'.
    1256      '7AGlwYASBVqH0Bk49dXpCviVV3dw/tI1Bvr7kMIIlh0NYUpjlF0BAYvcxSXmEVLKceHSCJm+PnbueBHbtkNwTXUNBzo6aGpq4sSZ'.
    1257      'GwT5H7BsF6Wdf1GWHQAoM0upeI9PT1yioS7B7tdaSdSuw7KsUGMAy7HYsmUztTW1nMwM0txssX1rlHjjS5jy/Uq2YkK/eJuLl6/z'.
    1258      'x+1xkslW6mrixGIODx8EFSlEBC0+tmXT0NhA2763iEUjnLv4C8XpUbSbAB1mKkGJ3J83Od77HW5EszvZSqK2iljMIeJaRGNuJePF'.
    1259      '6mspY7BJ1DXwQnCd2fxGRq5OUCz8xt72dyhMZcn++Cu3xu9SKhdp2b4ZHWnAtTSxmIWlhcIjlksR3lNBYzlxZsb7+f7ne+xtSzOd'.
    1260      'u83szH1OnThOPp/n+a0beeP1l4mvq+PU2Qyd+5PY1RuwlAqLYFaBfbTbyPSdfgaH77A//QF4f1O/vpr6RJyq+C5Kc/M8FbFxXItY'.
    1261      'xOHDrvfo/fxLDnbsJBp5BowBReVWYAzabeTh5ABDw7cWoNNL3YYYNtSv57lnn6Z+Qx01VeuIuBa2DV1HD3H63BAPZu4u1WGpeLHq'.
    1262      'Rh7+NcjA0O+0p4+CNwXigwnbWlQQdpuEpli+n+PIkcOc//YKuckJJFh2K2anrjFw+QZt6S6kPImIF/b+cqAJD1LihWAxC61twBTo'.
    1263      'fPcQF/oGsVW5ovHQlavs2/8+uYnRVSOUgHAmmAClBIOBwKC0gPjhIRgEIX2wg7NnwpZW3d3d4vs+vu8TBMGK51rvPM9b8hdteZxd'.
    1264      'LBbVR8feJDs0Rlv6GFKeXJ21rNRXESxMPR+CBUl0nN7PjtO+dye7Up/8v1I88bf/ixT/AO1/hZsqW+C6AAAAAElFTkSuQmCC' ;
    1265 
    1266         //==========================================================
    1267         // startconstrain.png
    1268         //==========================================================
    1269         $this->iBuiltinIcon[4][0]= 725 ;
    1270         $this->iBuiltinIcon[4][1]=
    1271      'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
    1272      'AAALDgAACw4BQL7hQQAAAAd0SU1FB9ALEREICJp5fBkAAAJSSURBVHic3dS9a1NRGMfx77kxtS+xqS9FG6p1ER3qVJpBQUUc3CRU'.
    1273      'BwURVLB1EAuKIP0THJQiiNRJBK3iJl18AyeltRZa0bbaJMbUNmlNSm5e7s25j0NqpSSmyag/OMM9POdzDuflwn8djz8gClVRrVEV'.
    1274      'ur4Bl1FTNSzLrSS6vbml0jUUwSXj8Qfk3PkLtLW2AeBIybmrgz3+gFzpucjlE4f4btuFTuWuCF5XDr3a3UPf6cM8GQvxzbsRAJdh'.
    1275      'ScfxSywml5j7mVypN0eGEJ0tebIre+zxB6Tv7jPReS2hREpOvpmUXU+H5eC913JnNCSRVE60pUVbWoZjprR39Yq70bdqj4pW7PEH'.
    1276      '5FpvL9e79jOTTHM7ssDL6CJZ08LbvAGnrpZg2mI2Z/MlZfN8IkxuSwu4V9+WIrj7zFlOHfXzKrLIi2SGh5ECKjnNVNxkQEc55vOw'.
    1277      'rb6O8JLFdHyJ+ayFElUeHvjwkfteL/V7fKTSkFvIQE4DoLI2Mz/muTkTApcBKIwaN8pwIUrKw+ajWwDknAO0d/r4zFaMuRS63sWm'.
    1278      'RoOdm+vRIriUYjKexrQV+t1o0YEVwfZSVJmD/dIABJuO0LG3lRFx0GOfiAELE9OgCrfU0XnIp5FwGLEy5WEAOxlR5uN+ARhP7GN3'.
    1279      '5w7Gv4bQI2+xpt4jjv2nWBmIlcExE2vDAHYioszBZXw6CPE4ADoWVHmd/tuwlZR9eXYyoszBfpiNQqaAOU5+TXRN+DeeenADPT9b'.
    1280      'EVgKVsutKPl0TGWGhwofoquaoKK4apsq/tH/e/kFwBMXLgAEKK4AAAAASUVORK5CYII=' ;
    1281 
    1282         //==========================================================
    1283         // calc.png
    1284         //==========================================================
    1285         $this->iBuiltinIcon[5][0]= 589 ;
    1286         $this->iBuiltinIcon[5][1]=
    1287      'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAA4AIwBbgMF12wAAAAlwSFlz'.
    1288      'AAALEQAACxEBf2RfkQAAAAd0SU1FB9AHBxQeFsqn0wQAAAHKSURBVHicnZWff+RAGIef3U/gcOEgUAgUCgcLhYXCwsHBQeGgUDgs'.
    1289      'FgMHB4VA/4Bg4XChWFgIFIqBwkJhsRAYeOGF+TQHmWSTTbKd9pU37/x45jvfTDITXEynAbdWKVQB0NazcVm0alcL4rJaRVzm+w/e'.
    1290      '3iwAkzbYRcnnYgI04GCvsxxSPabYaEdt2Ra6D0atcvvvDmyrMWBX1zPq2ircP/Tk98DiJtjV/fim6ziOCL6dDHZNhxQ3arIMsox4'.
    1291      'vejleL2Ay9+jaw6A+4OSICG2cacGKhsGxg+CxeqAQS0Y7BYJvowq7iGMOhXHEfzpvpQkA9bLKgOgWKt+4Lo1mM9hs9m17QNsJ70P'.
    1292      'Fjc/O52joogoX8MZKiBiAFxd9Z1vcj9wfSpUlDRNMcYQxzFpmnJ0FPH8nDe1MQaWSz9woQpWSZKEojDkeaWoKAyr1tlu+s48wfVx'.
    1293      'u7n5i7jthmGIiEGcT+36PP+gFeJrxWLhb0UA/lb4ggGs1T0rZs0zwM/ZjNfilcIY5tutPxgOW3F6dUX464LrKILLiw+A7WErrl+2'.
    1294      'rABG1EL/BilZP8DjU2uR4U+2E49P1Z8QJmNXUzl24A9GBT0IruCfi86d9x+D12RGzt+pNAAAAABJRU5ErkJggg==' ;
    1295 
    1296         //==========================================================
    1297         // mag.png
    1298         //==========================================================
    1299         $this->iBuiltinIcon[6][0]= 1415 ;
    1300         $this->iBuiltinIcon[6][1]=
    1301      'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
    1302      'AAALDAAACwwBP0AiyAAAAAd0SU1FB9ALDxEWDY6Ul+UAAAUESURBVHicdZVrbFRFGIafsyyF0nalV1R6WiggaAptlzsr1OgEogmC'.
    1303      '0IgoBAsBgkIrBAPEhBj/AP6xRTCUFEwRI4jcgsitXMrFCJptJWvBNpXYbbXtbtttt6e7e86ec/yxadlCfZPJZDIz73zzzjfvR2VL'.
    1304      'F7U+hf0HD2JduIzTFy6SlJRkPtkcDgdCCE65OxFC8NPV6wghyM7OptankJ2dzbSC5QghEEIgCSHog9PpNAF27dlN6miZuPgElB4/'.
    1305      'nmY3O7ZtByA1NVUCkGWZweD1eklJScESTbqxuIjrd+/x6uIl5M19hSy7nfGOeUxf+g7VjU1sKi7C4/GYsiyz7tAJAD4/cRaA1tZW'.
    1306      'AHIPnECUVGD1+/3U19ebG4uLeHf1akamjsIwoVnVCOvQEdLoVILYYmMo3PIxSBJflpSaDX5FAmju1QAYv/8k/s8+wLVxOU0jR2LZ'.
    1307      '8sMFAApWrCApbRRDrRZirBYSLBKaoRPQw3SFernf2sav7T0Ubt4KwL4FMwF4Vu8FoHBCKgCzDhwHwLIhZ7y5a89u4m2JhA0wTdDC'.
    1308      'OrphEjJMNElCHxKDEjaobmvlfo/Krj27CQQCJsCGJW8C0KXqAMxMiosQA8hZWcTFx9OsaniDKh1qmG7VoFsL0x0K06kbeAMhWpRe'.
    1309      '/KpG+gwHAKUnz7Dz3BUMw6DK18nuw99wt0Nh6VdHI8RJicmETQgFg7SFwjSrGv+oKp6ghldV6dZ0ugJBlF6FmCESQ2w2AIqXLsan'.
    1310      'BrFYLJTnTCBrdBqveeopWZiPFaBHUegJhegMqGgxEkHDwB/UaQ9rdIV06v0+TD2EEQjQFtAY0dsNgNvt5sialQAIIXh7wQKuVf6J'.
    1311      'gTsSccPDWlQstClBGjr9eHpVWvUQncEwdYEedF8noQ4vmYmpZMTH0nTvDn25vLbrNmu7bvfnsYEbAMnhcPDgwQPzUo2LJusw/mhp'.
    1312      'QwlHNO0KBAnoIfxtrcQMT2De1Mm891wyUzNlUlJSpIyMDBobGzlzr5rFM/Koq6vrP8ASGxsLwPmKcvIShjPGZiPOakE3VFB8hHwd'.
    1313      'vJAxhrk5L7Ly+RQuH/sWgPdXrwFg/6HDFBUsIj09nehfbAWwPWOT9n5RYhqGwarNWxkRM5TRCfF4U1PQsDDJFk9uYhwXvzvKjm3b'.
    1314      'KSsro3DJInNW5RXp7u2bAKSlpeH1esnPz6eqqgqLpmmcr3Fht9ulfaV7mZk1Bs+lM6T1djM9fhg5egDPpTNMy5TZsW07kydPYdWM'.
    1315      'aXx96ixOp9O8cfUa80srmDpjOgAulytiQqZpMnvObLbt/JTtHxXj9/tRVdU0DGOAufRpevPDTeac0hJyc3NxOOawfv161lVWS6eX'.
    1316      'z+9/UOCxu1VWVvaTRGv16NFfjB2bNeAQp9NpTpmSM4DcbrdL0WsGDKLRR+52uwe1yP8jb2lpYfikyY9t80n03UCWZeaXVjw1f+zs'.
    1317      'Oen+/d+pqanhzp2fKSsrw+l0mi6XiyPl5ZGITdN8fAVJwjRNJEmi1qfw1kw7siyTnJxMe3s71dXV3GpoZO64DG41NPJylvxU5D/e'.
    1318      'qJKsfWQD9IkaZ2RmUvr9aV4aGYcQgjfO3aWoYBF5eXm4ewIsu/CbdPz1aWb0/p1bNoOrQxlUiuiaFo3c3FyEEOx9+C9CCD6paaTW'.
    1319      'p/TXyYkTJ0Xe59jf7QOyAKDWp/QXxcFQ61P4pT3ShBBcvnUHIQTjxmX19/8BCeVg+/GPpskAAAAASUVORK5CYII=' ;
    1320 
    1321         //==========================================================
    1322         // lock.png
    1323         //==========================================================
    1324         $this->iBuiltinIcon[7][0]= 963 ;
    1325         $this->iBuiltinIcon[7][1]=
    1326      'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
    1327      'AAALCwAACwsBbQSEtwAAAAd0SU1FB9AKAw0XDmwMOwIAAANASURBVHic7ZXfS1t3GMY/3+PprI7aisvo2YU6h6ATA8JW4rrlsF4U'.
    1328      'qiAsF9mhl0N2cYTRy9G/wptAYWPD9iJtRy5asDe7cYFmyjaXOLaMImOrmkRrjL9yTmIS3120JybWQgfb3R74wuc8Lzw858vLOUpE'.
    1329      'OK6pqSm2trbY39+nu7tbPHYch7m5OcLhMIA67kWj0aMQEWk6tm17rNm2LSIie3t7ksvlJJ1OSyqVkls3Z8SyLMnlcqTTaVKpFLdu'.
    1330      'zmBZVj1HeY2VUti2TSQSQSml2bZdi0QirK2tMT09zerqKtlslqGhISYnJ4nHv2N+foFsNquOe9FotLlxOBwmk8lgWRbhcFgymYxY'.
    1331      'liUi0mqaJoAuIi2macrdO7fFsizx3to0Te7euV1vrXtXEgqFmJmZYWVlhXK5LB4/U9kwDL784kYV0A3DYHd3m4sXRymXywKoRi8U'.
    1332      'Ch01DgQCJBIJLMsiEAhIIpHw2uLz+eqtYrEYIqKZpimxWEyCwaCMjY01zYPBIJpXqVQqsby8TLVabWKA/v5+RkZGMAyDrq4ulFKH'.
    1333      'HsfjcWZnZ+ns7KTRqwcnk0mKxSKFQqGJlVKtruuSTCYB6O3trW9UI/v9/iZPB/j8s2HOnX0FgHfeXpeffnzK+fWf+fijvhLs0PtG'.
    1334      'D/n1OJ9+MsrlSwb3733DwMCAt1EyPj6uACYmJp56168NU6nUqFSE9nZdPE7+WqC/r4NKTagcCJVqDaUUB5VDAA4Pa9x7sMLlSwan'.
    1335      'WjRmv13D7/erpaWlo604qOp88OF7LC48rPNosMq5Th+Dgxd4/XyA1rbzADi7j8jnf2P++wdcvSr8MJ/i8eomAKlUqn41OsDAQDeD'.
    1336      'g++yuPCwzm/2vU8+n2a7sMFfj79mp7BBuVzioFSiXHJx3SKuW2Rzy0Up9dxnQVvODALQerqNRn4ZKe0Mvtc6TpzpmqbxalcY9Ato'.
    1337      '2v06t515C73YQftZB9GLnDrt4LoujuPgOA4Ui+C6yOpXJwZrJ7r/gv4P/u+D9W7fLxTz+1ScQxrZ3atRLaVxdjbY2d184R6/sLHe'.
    1338      'opHP7/Do90Ua+WWUyezzZHObP/7cfX54/dowE1d66s8TV3oE+Mfn+L/zb4XmHPjRG9YjAAAAAElFTkSuQmCC' ;
    1339 
    1340         //==========================================================
    1341         // stop.png
    1342         //==========================================================
    1343         $this->iBuiltinIcon[8][0]= 889 ;
    1344         $this->iBuiltinIcon[8][1]=
    1345      'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
    1346      'AAALDwAACw8BkvkDpQAAAAd0SU1FB9AJDwEvNyD6M/0AAAL2SURBVHic1ZTLaxVnGIefb2bO5OScHJN4oWrFNqcUJYoUEgU3/Qf6'.
    1347      'F7gwCkIrvdBLUtqqiLhSg9bgBduFSHZdiG5ctkJ3xRDbUFwUmghNzBDanPGMkzOX79LFJGPMOSd204U/+Bbzvd/78F4H/ieJdoad'.
    1348      'pZKxRFszAI/DcP0HazXY22v+HB01kee1PA/v3zfnjx4xgGnHcNZe7OvuNj+cOEF1ZATv5nUA4jhBSgmADCVWo8Ge2Of9wb18P/G7'.
    1349      'oUXmYi30zqlTVEdGWLh1g2D6MYlKkXGE0Vl8aa2GEB149+4xXSzyoOIw/mimiZV/DPb25pFOj13A9gOMEChhUEqhVYqWKUk9QAUp'.
    1350      'sT/P4s8PmKlUmNhQaIJbkDVqBbpw6wZ2zUc4Nm+ePku5p4eOrgpueQOFUoVCVxcD4+N07dpF9+5tVJeWGPBjhvr7WF1zC8ASgtcP'.
    1351      'H8a7eZ1odh4sh50nzwCw9ZNh3M4Stutiu0X2nB/LyjZ6lcIbVTpdQU/jWVPzLADM8+ZGBRdtC7wrF/O7bR99iu26VL86iU4SAH4b'.
    1352      'Po5d6AQhstMSvGyI4wS5FJBKSRwnzF8byx/u+PjzzMF1mfryQ1K/jnCahqp1xEopjFLoNEFJSRJHzF799gWHqa+/QKcSUXBI609f'.
    1353      'Al5W4teQSiHDOipNUKnMI13RvnOXAIEKQixvGWya98SC560MFwPiqEG86JM8q79Q06lvhnOndy5/B6GPCUOMUu3BQgg8z0M3GmBZ'.
    1354      'iGJn3v2VmsqnfzNx7FDueODuj8ROCFpjtG5TCmOYv32bJ09msP0ISydMfnAUgF8/O45RAA6WTPjlvXcB+Gn7FuRf/zAnNX6x3ARe'.
    1355      'PSdmqL+P/YHkwMGDOGWDZTlQcNBRhPEComgB/YeHfq2InF1kLlXUOkpMbio1bd7aATRD/X0M1lPeSlM2vt2X1XBZjZnpLG2tmZO6'.
    1356      'LbQVOIcP+HG2UauH3xgwBqOz9Cc3l1tC24Fz+MvUDroeGNb5if9H/1dM/wLPCYMw9fryKgAAAABJRU5ErkJggg==' ;
    1357 
    1358         //==========================================================
    1359         // error.png
    1360         //==========================================================
    1361         $this->iBuiltinIcon[9][0]= 541 ;
    1362         $this->iBuiltinIcon[9][1]=
    1363      'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaVBMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'.
    1364      'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpYiYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'.
    1365      'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTCAkUMSj9wWSOAAABLUlEQVR4'.
    1366      '2s2U3ZKCMAxGjfzJanFAXFkUle/9H9JUKA1gKTN7Yy6YMjl+kNPK5rlZVSuxf1ZRnlZxFYAm93NnIKvR+MEHUgqBXx93wZGIUrSe'.
    1367      'h+ctEgbpiMo3iQ4kioHCGxir/ZYUbr7AgPXs9bX0BCYM8vN/cPe8oQYzom3tVsSBMVHEoOJ5dm5F1RsIe9CtqGgRacCAkUvRtevT'.
    1368      'e2pd6vOWF+gCuc/brcuhyARakBU9FgK5bUBWdHEH8tHpDsZnRTZQGzdLVvQ3CzyYZiTAmSIODEwzFCAdJopuvbpeZDisJ4pKEcjD'.
    1369      'ijWPJhU1MjCo9dkYfiUVjQNTDKY6CVbR6A0niUSZjRwFanR0l9i/TyvGnFdqwStq5axMfDbyBksld/FUumvxS/Bd9VyJvQDWiiMx'.
    1370      'iOsCHgAAAABJRU5ErkJggg==' ;
    1371 
    1372         //==========================================================
    1373         // openfolder.png
    1374         //==========================================================
    1375         $this->iBuiltinIcon[10][0]= 2040 ;
    1376         $this->iBuiltinIcon[10][1]=
    1377      'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEANAAtwClFht71AAAAAlwSFlz'.
    1378      'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDQ4RIXMeaLcAAAd1SURBVHicxZd7jBXVHcc/58zcvTNzH8vusqw8FsTsKiCUUh5WBZXG'.
    1379      'GkOptmqwNWsWLKXFGlEpzZI0AWNKSy0WhDS22gJKtWlTsSRqzYIuLGB2WVvDIwQMZQMsy2OFfdzde+/OnHP6x907vJaFpjb9JZM5'.
    1380      'c85Mfp/f9/s7Jxn4P4e41gtSyp78WGvtfdEAcqDFYUOH9HS0NhGk9tPb/ilSyp789UUB2AMuqhQy3Uzm7HGkE6W3dTNZMRI3EcWO'.
    1381      'jf9ClLmWBT3dzW8jUsevWHCG3UpWl+IkHSxnbDh/Mcz12NevBcuWXTmf6TjnXvJ88gDmVB3pw3+nt3UzHa1NqMzBS2zqPLGFjtMN'.
    1382      'ZNr3XdW+qyqwZcFk76HX/tHWfuQvyO4W7qhaHwL8efkMRlRUpPv7rqD0RrJ+FgAjLy1a20OIxZJEEuNCRfIApj+om4bGM3u2/sYU'.
    1383      '9J41d8973f3Dhg1pISTV1dXXBRNJxPGFCzhou+DCQrScZOkktNaeDZjamgeZ9MgiYmVDccvHhjAzJw0NTh8/alyZMaVJicp0iTHj'.
    1384      'JpgNv38tjWUhhGROdbUL9W5/MH5XCkjlcibi+KIop5LVHLKEu8A/f4r286doa9pGrGwYAAsfqbbH3b8MgO/Nqgy6WvdbbXHMkEFJ'.
    1385      '4xUOMVEvaTZu3BgmvF4Yk4hz9rO/Ulr5cE9owae/rcGxohSOuiWkC2IjcIqKyPZm+OmCH7GhoZEF077EEzVVweAbJ+riEeO0Ey8y'.
    1386      'UubqOHn0AOgMwvf59txnBrSp9dgxKmf/+kIP1NY8SFk0jh5ajmNHAWg5b2E5EexojGHjbiVRMoRMNs0LC+Yz46vTuH3enN7BI8fr'.
    1387      'qFdo0BoVZNC9aVSQ4fNjBzEmQJiARxb+/AqYPMAVB5FsPU5v37g9OxgLhe14ZM5/ju052E6MNZvf5pmHHuLmmWOkEysxUtpGAtme'.
    1388      'dtHTflJkezqQto3jFRnLssyf1jydxiiM7zNnye/c3ZsqLu2BN5fcMfzrv/hby1tPzmRUoihcTJ87CwQI2yLtDcIqsIjYUf51qBlf'.
    1389      'OnScOSrdQUOMURkiXsLUzJnvbGhoBGDHH5cGyZLhOpYoNl5hqYnYEXOu5fDl9eYAHntx98n8hFHZcPHUuTSxSASAeK/CGIOxJJ0f'.
    1390      'bOGNPU280dgkq6Y2yu8vfjCIlwwzr+/ZQ/PHO0gOLuO5qsftDQ2NbN+4OCgqG6WTxWVaq6zpF+DiSHWnicdylp3r6aZTWthIOrNp'.
    1391      'ktHcvBu0sHX1Sm6ozB3B42d90zZA9bQp7PvgPSzXZfnqX/HS4DKKK2+x69Y/HURs26iBAN5ccsfw7774UcumF37C6f07KSt2OHji'.
    1392      'DEUJD0tISjyPrrSPlAKvN0JP/U4O1NfjuhG2rvklN1SOpfXwftpbTqAyKRrff5fb7rs9V1R7m4wlz2ihA3HpmXflUWyOH2umpLiY'.
    1393      'ui3v8M+6bWzfsRNbSgqkxaCkiy0simMuEWEhpcRzIhQWOIAh6tiAwS4owInFiTou5dOnMnl2NR++ujBwXEc9terD6M43nrj6LgAB'.
    1394      'QnDPA9/irtkP8JRS7Hr/3T6YekDQ1pEiEXOwpUVJzCVlZZFS4mZtkpEo9ChAkDp/jtLMBACy6S4RiQghLyv5cgBRPnKUOX6smUGF'.
    1395      'hSil0MYw9d77mPy1e5mnFE3batm3czvb6nYgEJztSFGU9LCRlMRdUjIH0+lnEMIwPNXD3NumoVJnrMCJaiciMUZfvQnz4QcBSvV1'.
    1396      'vjE5GK358t0zmXDnDB79saLpo20c+aSRD+t25JTp7GZQwsEWFiVxl6hlUf/WO9z32CxmL1rOe6u/I2KuwGhzLQCB7/sYY9Bah3el'.
    1397      'FKbvrrVm4vS7GH/7ncx+chEHGz7myCeNbPtoO0JI2jq78WIRLGkzsqs7V5SfFV5EovXACoiqqsfNpk2vo5VCWtYFBfoU0VoTBAFa'.
    1398      'a7TRaK2p+MoURk+cxMzq+Rzbv49DDbuo27UTW9h0dedssPxuK+kIfN8XxhgDYPVXf2Fh4XKtFIl4AiklAlBKAYRKKK36wHIweTCt'.
    1399      'NfHiEkaOn8j0+7/BmDFjaT30GbHywSxcuZkpFfFg+m1jjZ/NmnVvNfRvwd69e8WBA/uNFAIh4JVXXmHsmDHE4vEQQgjQ2lxQIm9N'.
    1400      'nz35q3BEOZOHzaG2thaA4mRU+L29It+IV21CpbRQfeMFC35gRB/M2rVrubnyZmLxWJhECBEmz/eHyo/7lMlH3LFFujsthNFCCGOu'.
    1401      '+WNyeUgpjSVzMKtWraKyshLPdcPEeYWCIEBdpIxSivr6eta8vI7d6+cGnhdV06pe1QP+F/QXWmuRL+jZZ58LlVmxYgUVFRV4rhtu'.
    1402      '4TzMxXAA6XRaRAtsYUkx8I/JtSJQOlSwpmZpCLN8+fPcdNNoHMfB9/0QJgRoP295TlR7UVv8xxZcHMuWIZ9/Hn35vG3JEGZpzVJG'.
    1403      'jx5N1IlitKahsZE1L69j69qHgx+urFX/lQL9JYdLlfnZihUhzOLFi8N3Ml1dthOxVH/f/8/CtqSJ2JaJ2JZ59J7RPsC/AViJsQS/'.
    1404      'dBntAAAAAElFTkSuQmCC' ;
    1405 
    1406         //==========================================================
    1407         // folder.png
    1408         //==========================================================
     1134        if( $aIdx < 0 || $aIdx >= $this->iLen ) {
     1135            JpGraphError::RaiseL(6010,$aIdx);
     1136//('Illegal icon index for Gantt builtin icon ['.$aIdx.']');
     1137        }
     1138        return Image::CreateFromString(base64_decode($this->iBuiltinIcon[$aIdx][1]));   
     1139    }
     1140
     1141    function PredefIcons() {
     1142        //==========================================================
     1143        // warning.png
     1144        //==========================================================
     1145        $this->iBuiltinIcon[0][0]= 1043 ;
     1146        $this->iBuiltinIcon[0][1]=
     1147            'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAA'.
     1148            'B3RJTUUH0wgKFSgilWPhUQAAA6BJREFUeNrtl91rHFUYh5/3zMx+Z5JNUoOamCZNaqTZ6IWIkqRiQWmi1IDetHfeiCiltgXBP8AL'.
     1149            '0SIUxf/AvfRSBS9EKILFFqyIH9CEmFZtPqrBJLs7c+b1YneT3WTTbNsUFPLCcAbmzPt73o9zzgzs2Z793231UOdv3w9k9Z2uzOdA'.
     1150            '5+2+79yNeL7Hl7hw7oeixRMZ6PJM26W18DNAm/Vh7lR8fqh97NmMF11es1iFpMATqdirwMNA/J4DpIzkr5YsAF1PO6gIMYHRdPwl'.
     1151            'oO2elmB+qH3sm7XozbkgYvy8SzYnZPtcblyM6I+5z3jQ+0vJfgpEu56BfI9vUkbyi2HZd1QJoeWRiAjBd4SDCW8SSAOy6wBHMzF7'.
     1152            'YdV2A+ROuvRPLfHoiSU0EMY/cDAIhxJeGngKaN1VgHyPL7NBxI1K9P4QxBzw3K1zJ/zkG8B9uwaQ7/HNsRZv9kohBGD0o7JqMYS/'.
     1153            '/ynPidQw/LrBiPBcS/yFCT95DvB2BWAy4575PaQbQKW+tPd3GCItu2odKI++YxiKu0d26oWmAD7paZU/rLz37VqIijD2YbnzNBBE'.
     1154            'IBHf8K8qjL7vYhCGErEU8CTg3xXAeMp96GrJEqkyXkm9Bhui1xfsunjdGhcYLq+IzjsGmBt5YH/cmJkFq6gIqlon3u4LxdKGuCIo'.
     1155            'Qu41g0E41po+2R33Xt5uz9kRIB2UTle7PnfKrROP1HD4sRjZlq0lzhwoZ6rDNeTi3nEg1si/7FT7kYQbXS6E5E65tA5uRF9tutq0'.
     1156            'K/VwAF+/FbIYWt6+tjQM/AqUms7A4Wy6d7YSfSNxgMmzi0ycWWworio4QJvj4LpuL5BqugTnXzzqJsJwurrlNhJXFaavW67NRw3F'.
     1157            'q+aJcCQVe9fzvJGmAY7/dPH0gi0f64OveGxa+usCuQMeZ0+kt8BVrX+qPO9Bzx0MgqBvs+a2PfDdYIf+WAjXU1ub4tqNaPPzRs8A'.
     1158            'blrli+WVn79cXn0cWKl+tGx7HLc7pu3CSmnfitL+l1UihAhwjFkPQev4K/fSABjBM8JCaFuurJU+rgW41SroA8aNMVNAFtgHJCsn'.
     1159            'XGy/58QVxAC9MccJtZ5kIzNlW440WrJ2ea4YPA9cAooA7i0A/gS+iqLoOpB1HOegqrYB3UBmJrAtQAJwpwPr1Ry92wVlgZsiYlW1'.
     1160            'uX1gU36dymgqYxJIJJNJT1W9QqHgNwFQBGYqo94OwHZQUuPD7ACglSvc+5n5T9m/wfJJX4U9qzEAAAAASUVORK5CYII=' ;
     1161
     1162        //==========================================================
     1163        // edit.png
     1164        //==========================================================
     1165        $this->iBuiltinIcon[1][0]= 959 ;
     1166        $this->iBuiltinIcon[1][1]=
     1167            'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAFgAWABY9j+ZuwAAAAlwSFlz'.
     1168            'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDAwbIEXOA6AAAAM8SURBVHicpdRPaBxlHMbx76ZvsmOTmm1dsEqQSIIsEmGVBAQjivEQ'.
     1169            'PAUJngpWsAWlBw8egpQepKwplN4ULEG9CjkEyUFKlSJrWTG0IU51pCsdYW2ncUPjdtp9Z+f3vuNhu8nKbmhaf5cZeGc+PO8zf1Lc'.
     1170            'm0KhkACICCKCMeaBjiLC0tLSnjNvPmuOHRpH0TZTU1M8zBi9wakzn7OFTs5sw8YYACYmJrre7HkeuVyu69qPF77hlT1XmZ0eQ03O'.
     1171            'wOLJTvhBx1rLz18VmJ0eY+jVd2FxDkKXnvYLHgb97OgLzE4ON9Hzc1B1QaQzsed5O0Lta3Ec89OnR5h5McfQ+Mw2qgQUnfBOPbZ3'.
     1172            'bK3l+xOvMT0+3ERLp5FNF6UEjcL32+DdVmGt5WLhDYYPZrbRqreFumXwql0S3w9tnDvLWD5PZigPpdOwuYpSCo3C8wU3UHxQdHbf'.
     1173            'cZIkNM6dxcnlUM4k1eUFMlUPpUADbpkttFarHe6oYqeOr6yt4RzMQHYUcUsQVtGicHDwKprViuLDkkOtVnsHCHZVRVy/zcj1i5Af'.
     1174            'h8AjdIts+hUcGcYPK3iBtKM3gD/uAzf/AdY2mmmVgy6X8YNNKmGIvyloPcB8SUin07RQ4EZHFdsdG0wkJEnEaHAJxvKEpSLeaokV'.
     1175            'r4zWmhUZYLlY4b1D03y5eIEWCtS7vsciAgiIxkQRabWOrlQor66y4pUphoJb1jiO4uO5o0S3q6RSqVbiOmC7VCEgAhLSaDQ48dH7'.
     1176            'vD46REY0iysegSjKQciRt99ib7qXwX0O+pG4teM6YKHLB9JMq4mTmF9/+AKA4wvLZByH7OgYL7+UY2qvw/7Bfg5kHiXjJFyv3CGO'.
     1177            'Y1rof+BW4t/XLiPG0DCGr79d4XzRxRnIMn98huXSTYyJ6et1UNYQhRvcinpJq86H3wGPPPM0iBDd+QffD1g4eZjLvuG7S1Wef26E'.
     1178            'J7L7eSx7gAHVg7V3MSbi6m/r93baBd6qQjerAJg/9Ql/XrvG0ON1+vv7GH3qSfY5fahUnSTpwZgIEQesaVXRPbHRG/xyJSAxMYlp'.
     1179            'EOm71HUINiY7mGb95l/8jZCyQmJjMDGJjUmsdCROtZ0n/P/Z8v4Fs2MTUUf7vYoAAAAASUVORK5CYII=' ;
     1180
     1181        //==========================================================
     1182        // endconstrain.png
     1183        //==========================================================
     1184        $this->iBuiltinIcon[2][0]= 666 ;
     1185        $this->iBuiltinIcon[2][1]=
     1186            'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
     1187            'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ALEREILkh0+eQAAAIXSURBVHictZU9aFNRFMd/N81HX77aptJUWmp1LHRpIcWhg5sIDlUQ'.
     1188            'LAXB4t7RRUpwEhy7iQ46CCIoSHcl0CFaoVARU2MFMYktadLXJNok7x2HtCExvuYFmnO4w/3gx+Gc/z1HKRTdMEdXqHbB/sgc/sic'.
     1189            'nDoYAI8XwDa8o1RMLT+2hAsigtTvbIGVqhX46szUifBGswUeCPgAGB7QeLk0X4Ork+HOxo1VgSqGASjMqkn8W4r4vVtEgI/RRQEL'.
     1190            'vaoGD85cl5V3nySR/S1mxWxab7f35PnntNyMJeRr9kCMqiHTy09EoeToLwggx6ymiMOD/VwcD7Oa/MHkcIiQx026WGYto5P/U+ZZ'.
     1191            '7gD0QwDuT5z9N3LrVPi0Xs543eQPKkRzaS54eviJIp4tMFQFMllAWN2qcRZHBnixNM8NYD162xq8u7ePSQ+GX2Pjwxc2dB2cLtB8'.
     1192            '7GgamCb0anBYBeChMtl8855CarclxU1gvViiUK4w2OMkNDnGeJ8bt9fH90yOnOkCwLFTwhzykhvtYzOWoBBbY//R3dbaNTYhf2RO'.
     1193            'QpeuUMzv188MlwuHy0H13HnE48UzMcL0WAtUHX8OxZHoG1URiFw7rnLLCswuSPD1ulze/iWjT2PSf+dBXRFtVVGIvzqph0pQL7VE'.
     1194            'avXYaXXxPwsnt0imdttCocMmZBdK7YU9D8wuNOW0nXc6QWzPsSa5naZ1beb9BbGB6dxGtMnXAAAAAElFTkSuQmCC' ;
     1195
     1196        //==========================================================
     1197        // mail.png
     1198        //==========================================================
     1199        $this->iBuiltinIcon[3][0]= 1122 ;
     1200        $this->iBuiltinIcon[3][1]=
     1201            'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
     1202            'AAALEAAACxABrSO9dQAAAAd0SU1FB9AJHAMfFvL9OU8AAAPfSURBVHictZRdaBRXFMd/987H7tbNx8aYtGCrEexDsOBDaKHFxirb'.
     1203            'h0qhsiY0ykppKq1osI99C4H2WSiFFMHWUhXBrjRi0uCmtSEUGgP1QWqhWjGkoW7M1kTX3WRn5p4+TJJNGolQ6IXDnDtz+N0z/3PP'.
     1204            'UWBIpdpYa23b9g09PZ2kUrOrvmUyGVKp1Ao/mUyi56YnVgWfO/P1CihAd/dJMpmaNROIRq8BkM1m0bH6TasC3j6QXgFdXI+DR6PR'.
     1205            'JX/Pno8B+KLnMKqlpUU8z8MYs2RBEDzWf9J+0RcRbMdxGBsbw/fmCXwPMUEYID4iAVp8wIRmDIHMo4yHSIBSASKC+CWE0C/PF9jU'.
     1206            '3B6Cp+4M07C5FUtKGNvGwQJctPgIsgD2wRhEIqAMGB+UQYkHJgYYZD7P1HwVlmWhHcfhyk83KeRGUW4t6CgoG5SNUS4KBWgQDUov'.
     1207            '7AGlwYASBVqH0Bk49dXpCviVV3dw/tI1Bvr7kMIIlh0NYUpjlF0BAYvcxSXmEVLKceHSCJm+PnbueBHbtkNwTXUNBzo6aGpq4sSZ'.
     1208            'GwT5H7BsF6Wdf1GWHQAoM0upeI9PT1yioS7B7tdaSdSuw7KsUGMAy7HYsmUztTW1nMwM0txssX1rlHjjS5jy/Uq2YkK/eJuLl6/z'.
     1209            'x+1xkslW6mrixGIODx8EFSlEBC0+tmXT0NhA2763iEUjnLv4C8XpUbSbAB1mKkGJ3J83Od77HW5EszvZSqK2iljMIeJaRGNuJePF'.
     1210            '6mspY7BJ1DXwQnCd2fxGRq5OUCz8xt72dyhMZcn++Cu3xu9SKhdp2b4ZHWnAtTSxmIWlhcIjlksR3lNBYzlxZsb7+f7ne+xtSzOd'.
     1211            'u83szH1OnThOPp/n+a0beeP1l4mvq+PU2Qyd+5PY1RuwlAqLYFaBfbTbyPSdfgaH77A//QF4f1O/vpr6RJyq+C5Kc/M8FbFxXItY'.
     1212            'xOHDrvfo/fxLDnbsJBp5BowBReVWYAzabeTh5ABDw7cWoNNL3YYYNtSv57lnn6Z+Qx01VeuIuBa2DV1HD3H63BAPZu4u1WGpeLHq'.
     1213            'Rh7+NcjA0O+0p4+CNwXigwnbWlQQdpuEpli+n+PIkcOc//YKuckJJFh2K2anrjFw+QZt6S6kPImIF/b+cqAJD1LihWAxC61twBTo'.
     1214            'fPcQF/oGsVW5ovHQlavs2/8+uYnRVSOUgHAmmAClBIOBwKC0gPjhIRgEIX2wg7NnwpZW3d3d4vs+vu8TBMGK51rvPM9b8hdteZxd'.
     1215            'LBbVR8feJDs0Rlv6GFKeXJ21rNRXESxMPR+CBUl0nN7PjtO+dye7Up/8v1I88bf/ixT/AO1/hZsqW+C6AAAAAElFTkSuQmCC' ;
     1216
     1217        //==========================================================
     1218        // startconstrain.png
     1219        //==========================================================
     1220        $this->iBuiltinIcon[4][0]= 725 ;
     1221        $this->iBuiltinIcon[4][1]=
     1222            'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
     1223            'AAALDgAACw4BQL7hQQAAAAd0SU1FB9ALEREICJp5fBkAAAJSSURBVHic3dS9a1NRGMfx77kxtS+xqS9FG6p1ER3qVJpBQUUc3CRU'.
     1224            'BwURVLB1EAuKIP0THJQiiNRJBK3iJl18AyeltRZa0bbaJMbUNmlNSm5e7s25j0NqpSSmyag/OMM9POdzDuflwn8djz8gClVRrVEV'.
     1225            'ur4Bl1FTNSzLrSS6vbml0jUUwSXj8Qfk3PkLtLW2AeBIybmrgz3+gFzpucjlE4f4btuFTuWuCF5XDr3a3UPf6cM8GQvxzbsRAJdh'.
     1226            'ScfxSywml5j7mVypN0eGEJ0tebIre+zxB6Tv7jPReS2hREpOvpmUXU+H5eC913JnNCSRVE60pUVbWoZjprR39Yq70bdqj4pW7PEH'.
     1227            '5FpvL9e79jOTTHM7ssDL6CJZ08LbvAGnrpZg2mI2Z/MlZfN8IkxuSwu4V9+WIrj7zFlOHfXzKrLIi2SGh5ECKjnNVNxkQEc55vOw'.
     1228            'rb6O8JLFdHyJ+ayFElUeHvjwkfteL/V7fKTSkFvIQE4DoLI2Mz/muTkTApcBKIwaN8pwIUrKw+ajWwDknAO0d/r4zFaMuRS63sWm'.
     1229            'RoOdm+vRIriUYjKexrQV+t1o0YEVwfZSVJmD/dIABJuO0LG3lRFx0GOfiAELE9OgCrfU0XnIp5FwGLEy5WEAOxlR5uN+ARhP7GN3'.
     1230            '5w7Gv4bQI2+xpt4jjv2nWBmIlcExE2vDAHYioszBZXw6CPE4ADoWVHmd/tuwlZR9eXYyoszBfpiNQqaAOU5+TXRN+DeeenADPT9b'.
     1231            'EVgKVsutKPl0TGWGhwofoquaoKK4apsq/tH/e/kFwBMXLgAEKK4AAAAASUVORK5CYII=' ;
     1232
     1233        //==========================================================
     1234        // calc.png
     1235        //==========================================================
     1236        $this->iBuiltinIcon[5][0]= 589 ;
     1237        $this->iBuiltinIcon[5][1]=
     1238            'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAA4AIwBbgMF12wAAAAlwSFlz'.
     1239            'AAALEQAACxEBf2RfkQAAAAd0SU1FB9AHBxQeFsqn0wQAAAHKSURBVHicnZWff+RAGIef3U/gcOEgUAgUCgcLhYXCwsHBQeGgUDgs'.
     1240            'FgMHB4VA/4Bg4XChWFgIFIqBwkJhsRAYeOGF+TQHmWSTTbKd9pU37/x45jvfTDITXEynAbdWKVQB0NazcVm0alcL4rJaRVzm+w/e'.
     1241            '3iwAkzbYRcnnYgI04GCvsxxSPabYaEdt2Ra6D0atcvvvDmyrMWBX1zPq2ircP/Tk98DiJtjV/fim6ziOCL6dDHZNhxQ3arIMsox4'.
     1242            'vejleL2Ay9+jaw6A+4OSICG2cacGKhsGxg+CxeqAQS0Y7BYJvowq7iGMOhXHEfzpvpQkA9bLKgOgWKt+4Lo1mM9hs9m17QNsJ70P'.
     1243            'Fjc/O52joogoX8MZKiBiAFxd9Z1vcj9wfSpUlDRNMcYQxzFpmnJ0FPH8nDe1MQaWSz9woQpWSZKEojDkeaWoKAyr1tlu+s48wfVx'.
     1244            'u7n5i7jthmGIiEGcT+36PP+gFeJrxWLhb0UA/lb4ggGs1T0rZs0zwM/ZjNfilcIY5tutPxgOW3F6dUX464LrKILLiw+A7WErrl+2'.
     1245            'rABG1EL/BilZP8DjU2uR4U+2E49P1Z8QJmNXUzl24A9GBT0IruCfi86d9x+D12RGzt+pNAAAAABJRU5ErkJggg==' ;
     1246
     1247        //==========================================================
     1248        // mag.png
     1249        //==========================================================
     1250        $this->iBuiltinIcon[6][0]= 1415 ;
     1251        $this->iBuiltinIcon[6][1]=
     1252            'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlz'.
     1253            'AAALDAAACwwBP0AiyAAAAAd0SU1FB9ALDxEWDY6Ul+UAAAUESURBVHicdZVrbFRFGIafsyyF0nalV1R6WiggaAptlzsr1OgEogmC'.
     1254            '0IgoBAsBgkIrBAPEhBj/AP6xRTCUFEwRI4jcgsitXMrFCJptJWvBNpXYbbXtbtttt6e7e86ec/yxadlCfZPJZDIz73zzzjfvR2VL'.
     1255            'F7U+hf0HD2JduIzTFy6SlJRkPtkcDgdCCE65OxFC8NPV6wghyM7OptankJ2dzbSC5QghEEIgCSHog9PpNAF27dlN6miZuPgElB4/'.
     1256            'nmY3O7ZtByA1NVUCkGWZweD1eklJScESTbqxuIjrd+/x6uIl5M19hSy7nfGOeUxf+g7VjU1sKi7C4/GYsiyz7tAJAD4/cRaA1tZW'.
     1257            'AHIPnECUVGD1+/3U19ebG4uLeHf1akamjsIwoVnVCOvQEdLoVILYYmMo3PIxSBJflpSaDX5FAmju1QAYv/8k/s8+wLVxOU0jR2LZ'.
     1258            '8sMFAApWrCApbRRDrRZirBYSLBKaoRPQw3SFernf2sav7T0Ubt4KwL4FMwF4Vu8FoHBCKgCzDhwHwLIhZ7y5a89u4m2JhA0wTdDC'.
     1259            'OrphEjJMNElCHxKDEjaobmvlfo/Krj27CQQCJsCGJW8C0KXqAMxMiosQA8hZWcTFx9OsaniDKh1qmG7VoFsL0x0K06kbeAMhWpRe'.
     1260            '/KpG+gwHAKUnz7Dz3BUMw6DK18nuw99wt0Nh6VdHI8RJicmETQgFg7SFwjSrGv+oKp6ghldV6dZ0ugJBlF6FmCESQ2w2AIqXLsan'.
     1261            'BrFYLJTnTCBrdBqveeopWZiPFaBHUegJhegMqGgxEkHDwB/UaQ9rdIV06v0+TD2EEQjQFtAY0dsNgNvt5sialQAIIXh7wQKuVf6J'.
     1262            'gTsSccPDWlQstClBGjr9eHpVWvUQncEwdYEedF8noQ4vmYmpZMTH0nTvDn25vLbrNmu7bvfnsYEbAMnhcPDgwQPzUo2LJusw/mhp'.
     1263            'QwlHNO0KBAnoIfxtrcQMT2De1Mm891wyUzNlUlJSpIyMDBobGzlzr5rFM/Koq6vrP8ASGxsLwPmKcvIShjPGZiPOakE3VFB8hHwd'.
     1264            'vJAxhrk5L7Ly+RQuH/sWgPdXrwFg/6HDFBUsIj09nehfbAWwPWOT9n5RYhqGwarNWxkRM5TRCfF4U1PQsDDJFk9uYhwXvzvKjm3b'.
     1265            'KSsro3DJInNW5RXp7u2bAKSlpeH1esnPz6eqqgqLpmmcr3Fht9ulfaV7mZk1Bs+lM6T1djM9fhg5egDPpTNMy5TZsW07kydPYdWM'.
     1266            'aXx96ixOp9O8cfUa80srmDpjOgAulytiQqZpMnvObLbt/JTtHxXj9/tRVdU0DGOAufRpevPDTeac0hJyc3NxOOawfv161lVWS6eX'.
     1267            'z+9/UOCxu1VWVvaTRGv16NFfjB2bNeAQp9NpTpmSM4DcbrdL0WsGDKLRR+52uwe1yP8jb2lpYfikyY9t80n03UCWZeaXVjw1f+zs'.
     1268            'Oen+/d+pqanhzp2fKSsrw+l0mi6XiyPl5ZGITdN8fAVJwjRNJEmi1qfw1kw7siyTnJxMe3s71dXV3GpoZO64DG41NPJylvxU5D/e'.
     1269            'qJKsfWQD9IkaZ2RmUvr9aV4aGYcQgjfO3aWoYBF5eXm4ewIsu/CbdPz1aWb0/p1bNoOrQxlUiuiaFo3c3FyEEOx9+C9CCD6paaTW'.
     1270            'p/TXyYkTJ0Xe59jf7QOyAKDWp/QXxcFQ61P4pT3ShBBcvnUHIQTjxmX19/8BCeVg+/GPpskAAAAASUVORK5CYII=' ;
     1271
     1272        //==========================================================
     1273        // lock.png
     1274        //==========================================================
     1275        $this->iBuiltinIcon[7][0]= 963 ;
     1276        $this->iBuiltinIcon[7][1]=
     1277            'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
     1278            'AAALCwAACwsBbQSEtwAAAAd0SU1FB9AKAw0XDmwMOwIAAANASURBVHic7ZXfS1t3GMY/3+PprI7aisvo2YU6h6ATA8JW4rrlsF4U'.
     1279            'qiAsF9mhl0N2cYTRy9G/wptAYWPD9iJtRy5asDe7cYFmyjaXOLaMImOrmkRrjL9yTmIS3120JybWQgfb3R74wuc8Lzw858vLOUpE'.
     1280            'OK6pqSm2trbY39+nu7tbPHYch7m5OcLhMIA67kWj0aMQEWk6tm17rNm2LSIie3t7ksvlJJ1OSyqVkls3Z8SyLMnlcqTTaVKpFLdu'.
     1281            'zmBZVj1HeY2VUti2TSQSQSml2bZdi0QirK2tMT09zerqKtlslqGhISYnJ4nHv2N+foFsNquOe9FotLlxOBwmk8lgWRbhcFgymYxY'.
     1282            'liUi0mqaJoAuIi2macrdO7fFsizx3to0Te7euV1vrXtXEgqFmJmZYWVlhXK5LB4/U9kwDL784kYV0A3DYHd3m4sXRymXywKoRi8U'.
     1283            'Ch01DgQCJBIJLMsiEAhIIpHw2uLz+eqtYrEYIqKZpimxWEyCwaCMjY01zYPBIJpXqVQqsby8TLVabWKA/v5+RkZGMAyDrq4ulFKH'.
     1284            'HsfjcWZnZ+ns7KTRqwcnk0mKxSKFQqGJlVKtruuSTCYB6O3trW9UI/v9/iZPB/j8s2HOnX0FgHfeXpeffnzK+fWf+fijvhLs0PtG'.
     1285            'D/n1OJ9+MsrlSwb3733DwMCAt1EyPj6uACYmJp56168NU6nUqFSE9nZdPE7+WqC/r4NKTagcCJVqDaUUB5VDAA4Pa9x7sMLlSwan'.
     1286            'WjRmv13D7/erpaWlo604qOp88OF7LC48rPNosMq5Th+Dgxd4/XyA1rbzADi7j8jnf2P++wdcvSr8MJ/i8eomAKlUqn41OsDAQDeD'.
     1287            'g++yuPCwzm/2vU8+n2a7sMFfj79mp7BBuVzioFSiXHJx3SKuW2Rzy0Up9dxnQVvODALQerqNRn4ZKe0Mvtc6TpzpmqbxalcY9Ato'.
     1288            '2v06t515C73YQftZB9GLnDrt4LoujuPgOA4Ui+C6yOpXJwZrJ7r/gv4P/u+D9W7fLxTz+1ScQxrZ3atRLaVxdjbY2d184R6/sLHe'.
     1289            'opHP7/Do90Ua+WWUyezzZHObP/7cfX54/dowE1d66s8TV3oE+Mfn+L/zb4XmHPjRG9YjAAAAAElFTkSuQmCC' ;
     1290
     1291        //==========================================================
     1292        // stop.png
     1293        //==========================================================
     1294        $this->iBuiltinIcon[8][0]= 889 ;
     1295        $this->iBuiltinIcon[8][1]=
     1296            'iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
     1297            'AAALDwAACw8BkvkDpQAAAAd0SU1FB9AJDwEvNyD6M/0AAAL2SURBVHic1ZTLaxVnGIefb2bO5OScHJN4oWrFNqcUJYoUEgU3/Qf6'.
     1298            'F7gwCkIrvdBLUtqqiLhSg9bgBduFSHZdiG5ctkJ3xRDbUFwUmghNzBDanPGMkzOX79LFJGPMOSd204U/+Bbzvd/78F4H/ieJdoad'.
     1299            'pZKxRFszAI/DcP0HazXY22v+HB01kee1PA/v3zfnjx4xgGnHcNZe7OvuNj+cOEF1ZATv5nUA4jhBSgmADCVWo8Ge2Of9wb18P/G7'.
     1300            'oUXmYi30zqlTVEdGWLh1g2D6MYlKkXGE0Vl8aa2GEB149+4xXSzyoOIw/mimiZV/DPb25pFOj13A9gOMEChhUEqhVYqWKUk9QAUp'.
     1301            'sT/P4s8PmKlUmNhQaIJbkDVqBbpw6wZ2zUc4Nm+ePku5p4eOrgpueQOFUoVCVxcD4+N07dpF9+5tVJeWGPBjhvr7WF1zC8ASgtcP'.
     1302            'H8a7eZ1odh4sh50nzwCw9ZNh3M4Stutiu0X2nB/LyjZ6lcIbVTpdQU/jWVPzLADM8+ZGBRdtC7wrF/O7bR99iu26VL86iU4SAH4b'.
     1303            'Po5d6AQhstMSvGyI4wS5FJBKSRwnzF8byx/u+PjzzMF1mfryQ1K/jnCahqp1xEopjFLoNEFJSRJHzF799gWHqa+/QKcSUXBI609f'.
     1304            'Al5W4teQSiHDOipNUKnMI13RvnOXAIEKQixvGWya98SC560MFwPiqEG86JM8q79Q06lvhnOndy5/B6GPCUOMUu3BQgg8z0M3GmBZ'.
     1305            'iGJn3v2VmsqnfzNx7FDueODuj8ROCFpjtG5TCmOYv32bJ09msP0ISydMfnAUgF8/O45RAA6WTPjlvXcB+Gn7FuRf/zAnNX6x3ARe'.
     1306            'PSdmqL+P/YHkwMGDOGWDZTlQcNBRhPEComgB/YeHfq2InF1kLlXUOkpMbio1bd7aATRD/X0M1lPeSlM2vt2X1XBZjZnpLG2tmZO6'.
     1307            'LbQVOIcP+HG2UauH3xgwBqOz9Cc3l1tC24Fz+MvUDroeGNb5if9H/1dM/wLPCYMw9fryKgAAAABJRU5ErkJggg==' ;
     1308
     1309        //==========================================================
     1310        // error.png
     1311        //==========================================================
     1312        $this->iBuiltinIcon[9][0]= 541 ;
     1313        $this->iBuiltinIcon[9][1]=
     1314            'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAaVBMVEX//////2Xy8mLl5V/Z2VvMzFi/v1WyslKlpU+ZmUyMjEh/'.
     1315            'f0VyckJlZT9YWDxMTDjAwMDy8sLl5bnY2K/MzKW/v5yyspKlpYiYmH+MjHY/PzV/f2xycmJlZVlZWU9MTEXY2Ms/PzwyMjLFTjea'.
     1316            'AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAHdElNRQfTCAkUMSj9wWSOAAABLUlEQVR4'.
     1317            '2s2U3ZKCMAxGjfzJanFAXFkUle/9H9JUKA1gKTN7Yy6YMjl+kNPK5rlZVSuxf1ZRnlZxFYAm93NnIKvR+MEHUgqBXx93wZGIUrSe'.
     1318            'h+ctEgbpiMo3iQ4kioHCGxir/ZYUbr7AgPXs9bX0BCYM8vN/cPe8oQYzom3tVsSBMVHEoOJ5dm5F1RsIe9CtqGgRacCAkUvRtevT'.
     1319            'e2pd6vOWF+gCuc/brcuhyARakBU9FgK5bUBWdHEH8tHpDsZnRTZQGzdLVvQ3CzyYZiTAmSIODEwzFCAdJopuvbpeZDisJ4pKEcjD'.
     1320            'ijWPJhU1MjCo9dkYfiUVjQNTDKY6CVbR6A0niUSZjRwFanR0l9i/TyvGnFdqwStq5axMfDbyBksld/FUumvxS/Bd9VyJvQDWiiMx'.
     1321            'iOsCHgAAAABJRU5ErkJggg==' ;
     1322
     1323        //==========================================================
     1324        // openfolder.png
     1325        //==========================================================
     1326        $this->iBuiltinIcon[10][0]= 2040 ;
     1327        $this->iBuiltinIcon[10][1]=
     1328            'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAZiS0dEANAAtwClFht71AAAAAlwSFlz'.
     1329            'AAALEAAACxABrSO9dQAAAAd0SU1FB9AKDQ4RIXMeaLcAAAd1SURBVHicxZd7jBXVHcc/58zcvTNzH8vusqw8FsTsKiCUUh5WBZXG'.
     1330            'GkOptmqwNWsWLKXFGlEpzZI0AWNKSy0WhDS22gJKtWlTsSRqzYIuLGB2WVvDIwQMZQMsy2OFfdzde+/OnHP6x907vJaFpjb9JZM5'.
     1331            'c85Mfp/f9/s7Jxn4P4e41gtSyp78WGvtfdEAcqDFYUOH9HS0NhGk9tPb/ilSyp789UUB2AMuqhQy3Uzm7HGkE6W3dTNZMRI3EcWO'.
     1332            'jf9ClLmWBT3dzW8jUsevWHCG3UpWl+IkHSxnbDh/Mcz12NevBcuWXTmf6TjnXvJ88gDmVB3pw3+nt3UzHa1NqMzBS2zqPLGFjtMN'.
     1333            'ZNr3XdW+qyqwZcFk76HX/tHWfuQvyO4W7qhaHwL8efkMRlRUpPv7rqD0RrJ+FgAjLy1a20OIxZJEEuNCRfIApj+om4bGM3u2/sYU'.
     1334            '9J41d8973f3Dhg1pISTV1dXXBRNJxPGFCzhou+DCQrScZOkktNaeDZjamgeZ9MgiYmVDccvHhjAzJw0NTh8/alyZMaVJicp0iTHj'.
     1335            'JpgNv38tjWUhhGROdbUL9W5/MH5XCkjlcibi+KIop5LVHLKEu8A/f4r286doa9pGrGwYAAsfqbbH3b8MgO/Nqgy6WvdbbXHMkEFJ'.
     1336            '4xUOMVEvaTZu3BgmvF4Yk4hz9rO/Ulr5cE9owae/rcGxohSOuiWkC2IjcIqKyPZm+OmCH7GhoZEF077EEzVVweAbJ+riEeO0Ey8y'.
     1337            'UubqOHn0AOgMwvf59txnBrSp9dgxKmf/+kIP1NY8SFk0jh5ajmNHAWg5b2E5EexojGHjbiVRMoRMNs0LC+Yz46vTuH3enN7BI8fr'.
     1338            'qFdo0BoVZNC9aVSQ4fNjBzEmQJiARxb+/AqYPMAVB5FsPU5v37g9OxgLhe14ZM5/ju052E6MNZvf5pmHHuLmmWOkEysxUtpGAtme'.
     1339            'dtHTflJkezqQto3jFRnLssyf1jydxiiM7zNnye/c3ZsqLu2BN5fcMfzrv/hby1tPzmRUoihcTJ87CwQI2yLtDcIqsIjYUf51qBlf'.
     1340            'OnScOSrdQUOMURkiXsLUzJnvbGhoBGDHH5cGyZLhOpYoNl5hqYnYEXOu5fDl9eYAHntx98n8hFHZcPHUuTSxSASAeK/CGIOxJJ0f'.
     1341            'bOGNPU280dgkq6Y2yu8vfjCIlwwzr+/ZQ/PHO0gOLuO5qsftDQ2NbN+4OCgqG6WTxWVaq6zpF+DiSHWnicdylp3r6aZTWthIOrNp'.
     1342            'ktHcvBu0sHX1Sm6ozB3B42d90zZA9bQp7PvgPSzXZfnqX/HS4DKKK2+x69Y/HURs26iBAN5ccsfw7774UcumF37C6f07KSt2OHji'.
     1343            'DEUJD0tISjyPrrSPlAKvN0JP/U4O1NfjuhG2rvklN1SOpfXwftpbTqAyKRrff5fb7rs9V1R7m4wlz2ihA3HpmXflUWyOH2umpLiY'.
     1344            'ui3v8M+6bWzfsRNbSgqkxaCkiy0simMuEWEhpcRzIhQWOIAh6tiAwS4owInFiTou5dOnMnl2NR++ujBwXEc9terD6M43nrj6LgAB'.
     1345            'QnDPA9/irtkP8JRS7Hr/3T6YekDQ1pEiEXOwpUVJzCVlZZFS4mZtkpEo9ChAkDp/jtLMBACy6S4RiQghLyv5cgBRPnKUOX6smUGF'.
     1346            'hSil0MYw9d77mPy1e5mnFE3batm3czvb6nYgEJztSFGU9LCRlMRdUjIH0+lnEMIwPNXD3NumoVJnrMCJaiciMUZfvQnz4QcBSvV1'.
     1347            'vjE5GK358t0zmXDnDB79saLpo20c+aSRD+t25JTp7GZQwsEWFiVxl6hlUf/WO9z32CxmL1rOe6u/I2KuwGhzLQCB7/sYY9Bah3el'.
     1348            'FKbvrrVm4vS7GH/7ncx+chEHGz7myCeNbPtoO0JI2jq78WIRLGkzsqs7V5SfFV5EovXACoiqqsfNpk2vo5VCWtYFBfoU0VoTBAFa'.
     1349            'a7TRaK2p+MoURk+cxMzq+Rzbv49DDbuo27UTW9h0dedssPxuK+kIfN8XxhgDYPVXf2Fh4XKtFIl4AiklAlBKAYRKKK36wHIweTCt'.
     1350            'NfHiEkaOn8j0+7/BmDFjaT30GbHywSxcuZkpFfFg+m1jjZ/NmnVvNfRvwd69e8WBA/uNFAIh4JVXXmHsmDHE4vEQQgjQ2lxQIm9N'.
     1351            'nz35q3BEOZOHzaG2thaA4mRU+L29It+IV21CpbRQfeMFC35gRB/M2rVrubnyZmLxWJhECBEmz/eHyo/7lMlH3LFFujsthNFCCGOu'.
     1352            '+WNyeUgpjSVzMKtWraKyshLPdcPEeYWCIEBdpIxSivr6eta8vI7d6+cGnhdV06pe1QP+F/QXWmuRL+jZZ58LlVmxYgUVFRV4rhtu'.
     1353            '4TzMxXAA6XRaRAtsYUkx8I/JtSJQOlSwpmZpCLN8+fPcdNNoHMfB9/0QJgRoP295TlR7UVv8xxZcHMuWIZ9/Hn35vG3JEGZpzVJG'.
     1354            'jx5N1IlitKahsZE1L69j69qHgx+urFX/lQL9JYdLlfnZihUhzOLFi8N3Ml1dthOxVH/f/8/CtqSJ2JaJ2JZ59J7RPsC/AViJsQS/'.
     1355            'dBntAAAAAElFTkSuQmCC' ;
     1356
     1357        //==========================================================
     1358        // folder.png
     1359        //==========================================================
    14091360        $this->iBuiltinIcon[11][0]= 1824 ;
    1410         $this->iBuiltinIcon[11][1]=
    1411      'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
    1412      'AAALEAAACxABrSO9dQAAAAd0SU1FB9ECAQgFFyd9cRUAAAadSURBVHiczdhvbBP3Hcfx9/2xfefEOA5JoCNNnIT8AdtZmYBETJsI'.
    1413      '6+jQOlQihT1AYgytqzZpD1atfyYqlT1h0lRpT7aRJ4NQpRvZGELVuo5Ua9jEJDIETQsNQyPBsUJMWGPnj//e+e72wNg4xElMR6ed'.
    1414      'ZNln3933dZ/f93f6yfB/sgmrHdDV1WXlPg8NDZUDScD8LFFFEZZlWYZhWMFg0Orq6sq/gDJAfFy1iiZy9OjrVnj4JzQ1rMWqfxm/'.
    1415      '309jYyNtbW0kEgnu3bvH4cOH88c/jqSKQl4/XGkd+eVtAN46up1LH92ktqYS++ZX8Pv9NDQ0sGnTJlKpFOFwmO7u7vy5IyMjeVRd'.
    1416      'XV1+WEOh0IrY4pDnq6wXX/sTiCJaMkFZdRNqxefoe7VtCSqXVDqdZnZ2ltraWkzTpKqqijt3JpFlG7dvj7NzZ1f++qFQyA3EClHL'.
    1417      'Ql743nFkhxPDtJAd5eTaYSVUfX09lZWVlJWVIUnSg7sVQMBCUcu4ceMGe/bsIRQK1QAzOcyykIM9P0KyudAyCWyqG8nhwqa4SkLt'.
    1418      '3r0bVVVxu924XC40TUOWZUQxe97CwgIdHR2LMHIxSCaVInVvFElxE0vMY1Pd2NUKJMWNTXHlUfF//4vETJCelwbpFm3MjP2dt37x'.
    1419      'AlN+PzU1NViWRSwW4+7du3g8HjweD4qi5EFAJzAExIpCANbooxhplfB0FJvTg6xWIqsVRVF6MopkU3FXPcnkJxGU0VEAdF2noqKC'.
    1420      'W3/8DpnqLjzep2lubsblcjE8PExHR8fboVDID9xYFpLBDpJF0jDQIncQpWlkm31FlFLtp9PfyuW/vYQj1kPSuRW/38+lj27S2Q7v'.
    1421      '/aWXUBVUffVNtm3blivVCEwsC5Eyc5iiApEpDEAXMqQdldhSiWVQHjJagud+8Fuexck/zv+K82dfoSbSCsDe75/km+4GVPd6+l5t'.
    1422      '4zJHcqVUYN2yEEtZQDCSJCueRAYsPY49HsFIZVG6p25JUumFafT4DKJN4amtT7Nz38sk5+5A70HMtEYyMkFiZhxzjQ/poXrLQrRU'.
    1423      'DFGEeFpAlkQkm4pRiCpIKodKzk0T/2QMh+piPjxKZPwiSkUtu/b9mNnJEWS7E8nhAmvpM60oJDkXJxqNozxRRUxPIesispBBlsXV'.
    1424      'UaKEFo8gzoaJhz8s2lOmrpUG+WBhJ9/60g+Z+fDXTAXfxllRjl1VkO0OFATsYhYliiK21ZKKhhHnFveUqSdKgwAEOp7F2v51vvw8'.
    1425      'XH7/N1wd/BlTweuUV65BdtgfoLTSkipsdD3tRi0VYpommUwGwzDwdT5HYEc3giAwcvH3jLz3BlPB67jWeZBEKYsSBWwpHZtNKo4q'.
    1426      'aHTDsJeeiGEYWJaFZVmYpommaRiGQdPnv0bb1m8gSRL/vPIOV979aR4lmAJ2p4qCgCxksNuKJ6VNpx4NYhgGpmkuQhmGQTqdxjAM'.
    1427      'qr2d7HtxEEEQuH1tkKvvvkF44tqDnrIcKJKAPf1g+LAUElq8dIiu60sApmnm93Pfzc7OYhgGrie+wFe++ztcLhcT1wf54PzPCU9c'.
    1428      'w7XWjWS3IdsdOAUBWZAxrRJnTQ6SG5bce2FCpmkughmGQSqVYm5uDtnj44sH38TtdhP6+Dwf//V4ttHXrkGURZJaic8RgHQ6jWma'.
    1429      'SJKUL5RLKNfIOczDKF3XSSaTRCIRhLJWntp3nGfWrSMxc5OLf3iNP4+68T9Ub9nF76lTpxgfHycajZJKpdA0LZ9GbjYV7hcDWZaF'.
    1430      'pmnMz88Ti8UYunSLmu1HFi2aVkxkaGjINTY2ttDb24vX6+XQoUNs3ryZ8vJyIDu1BUFYkkxhgxeiWlpaOHPmDE1NTdTX1xe98eWG'.
    1431      'JnF/9dQZCoXUYDA4AOD1ejlw4ACtra2Ul5fniwmCkEcUJiUIAoFAgL6+Pnw+H21tbfT39z8SxCS7hHsfWH9/8dL4MKqnp4eWlhac'.
    1432      'TmcekEvMNE2am5s5ceIEgUCA9vZ2Tp48ic/nY3j4UsmQHCYOjJHtpeBKqL1799Lc3IzT6UTXdRobGxkYGKC9vZ3W1tZ8Ko86NJ8a'.
    1433      'tXHjRo4dO8bp06fZsmULGzZsoL+/n0AggNfr5ezZs/8VpGTU5OSkc//+/acBfD4f1dXV7Nq1i4aGBs6dO4fP5+Pq1SuPBbIiyjTN'.
    1434      'RUnV1dUNXLhwAa/Xy44dO4jFYgBEo9FFF1r134BPuYlk16LrAYXsAlmtq6sbKDwoFAp9m+ykuP5ZQVZF3f8tCdwCov8LyHIoAANI'.
    1435      'AXf/A1TI0XCDh7OWAAAAAElFTkSuQmCC' ;
    1436 
    1437         //==========================================================
    1438         // file_important.png
    1439         //==========================================================
    1440         $this->iBuiltinIcon[12][0]= 1785 ;
    1441         $this->iBuiltinIcon[12][1]=
    1442      'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
    1443      'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ECDAcjDeD3lKsAAAZ2SURBVHicrZhPaFzHHcc/897s7lutJCsr2VHsOHWMk0MPbsBUrcnF'.
    1444      'OFRdSo6FNhdB6SGHlpDmYtJCDyoxyKe6EBxKQkt7KKL0T6ABo0NbciqigtC6PhWKI2NFqqxdSd7V2/dmftPDvPd212t55dCBYfbN'.
    1445      'zpvfZ77z+/1mdhUjytWrV93Hf/24eD5z9gwiMlDjOKbb7dLtdhER2u02u7u73Lp1CxEZBw4AeZwdNQqkMd9wbziFGINJUt6rRbz5'.
    1446      '1ptUq1XK5TJBEAAUMHt7e+zu7gKwvLzMysoKwAng/uNg9CgQgFKlgg1DUJ67Vqtx6tQpZmdniaIIpRTOOZRSdDoddnZ2aLfbLC8v'.
    1447      's7S0xJUrV7ZGwQSj1PhhfRodVdDlMrpc5vup5Z2fvMPdu3fZ29vDWjvwztjYGPV6nVqtRqVS4dKlSywtLQFsAdOH2XwsCEApg3jl'.
    1448      'w98Rak2gvYjNZpNms0mSJDjnHgkDMDc3dySYQ0Ea8w139YUX0OUKulzyg7UmCEO+l1huvHuDra0t9vf3h1TJYSqVypFhHquIrlQI'.
    1449      'S5qv/uIDAC7/4bcEQYAKvK+0Wq1DVQGIoog7d+4cCeaRII35hrt+8SsEOkRlUaEyR0UpFIrXHxyMVKVUKnHv3r0jwRwaNelBjBjL'.
    1450      'Sz/7KYuLiwAsLi7y4z/9kY9e+TpkCuSqjI+Po7XuAWeKXLt2DWNMUZMkwRjDhQsXWFtbK6JpCCT3jfQgxomPtPX19YHWicM5x3c2'.
    1451      '73Pj3Ru8/aO3mZqaolKpoHVvyuvXr/Ppnf/Q7uzz380NPtu4y/qnG+ztd1hfX2dtbQ3gIvDnRyqSxl1UoPjyz98D4PTp0wPtq39Z'.
    1452      '4fdzLxegrVaLVqvF5OQkYRgWqpRKJZ77wvNsbW1RG5tgfKLOTH2G7Z1twqBQrgrMDvhInjfSOCY5iIv+hYWFgRZArEWsZWF941Bf'.
    1453      'SdMUgMnJCWpjVU4cn+HUyePM1Gc4+fRUPkzBI5w1jbukcczLv/5l0XfmzJmBFuCba38r/CRXpT+CrDUoZ0jjB4RYonJAOYRobJKT'.
    1454      'z5zgqfqxAbsFSH6mpHFM2qdGXh4VnoViD6mSJF2cTQeqDqBaKVHWmonJCWpZjhkC6anR5WsffTgwaHV1FaUUq6urA/2v3f5k4LnV'.
    1455      'arG9tUn3oI2YBCcWHYAxMVYs1qZEZY2SFB2aYZDGfMN9d7uJiWPSeFiNo5Rclc3NTXZbO6RpF7EJVixYA9agwwDnUiqlEPdQ3imi'.
    1456      'Jo27BGHIt/7x9yEjc3Nzh27Na7c/4TdffKl4bja3ae5MUIu0T/HOEIaOpJt4gwoSsVTK4SBIY77hFtY3ABBjBiZ90rKwvsH77/+K'.
    1457      't37wOhO1iPpTk4SBw1mLsz6CnKQ4l3qV+kE+t9XHlNZOk+bUJLVIE1VCcIJWQmJ6qjj30NbcXLkZMt8YPig+Z3n1G5fZ39/j/vY2'.
    1458      '9ckqZT2Ochbn0p4qNkU/dDfUADdXbh4HXgRO4zNdEU0XL1784PLly5w9e7Z4SazFOfGrEotDcOKrcoJPmrYIXf/Zop3QNd1skuGt'.
    1459      'cUAb2MgAxvHZTgFUq1Wmp6eZnZ0F8JlTjDduDThBnDeECEoJtbGIp6enqEblzCcEZ1PECU4yVRiOGgd0gc+AB0CZvkv1sWPHOHfu'.
    1460      'HOfPn8da41cpkkltEBEPJhYnBkTQJcdYVKGkgRxCfBsq5xXNgAa2Bn+hjTOgHEKBP8pzRUxykIH4ifLJRTJAl+UMBJzPHQ6bfe/f'.
    1461      'cWIzPxlUpD+zugzIZtVk1d8znBAqRxgoQuVQgSJQ3h9C5QhDRYgjUILCAzlnEdsHYTKfMTEBcP7F54YUGVmc2GLlIn6ve6v0ahSt'.
    1462      '8X25TzjJ+rIx1grKpQPWR4LkGVVsMgghvS0qjPdvm5OeceOTWA5Evo2mFzkjQfL7hZPUy5yvvF/uPFQL3+nbDmsLCEmT3sTmCTNr'.
    1463      'rogT6yFsOix3ftw7OwQhkvSU6CuinhCk0+kAkFoBazEEICHaHHiPVmU0gnUp4EAc1mYrF0EBVpwPi34VrBkwPxKk3W5ju/e5/c+d'.
    1464      'bGUHIAIuydTIE5zfc5Wr4lJcahHnHTP3CVGm78DrgY38N+DEibp7dmYKdAQmBh1hjEFjis+9CTWYGK21H6PxPyOI0DobYwzZF/z7'.
    1465      '7jadTvJtYG0kCD7lfwl49ijgT1gc0AH+dZSJA/xB+Mz/GSIvFoj/B7H1mAd8CO/zAAAAAElFTkSuQmCC' ;
    1466 
    1467         $this->iLen = count($this->iBuiltinIcon);
     1361        $this->iBuiltinIcon[11][1]=
     1362            'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
     1363            'AAALEAAACxABrSO9dQAAAAd0SU1FB9ECAQgFFyd9cRUAAAadSURBVHiczdhvbBP3Hcfx9/2xfefEOA5JoCNNnIT8AdtZmYBETJsI'.
     1364            '6+jQOlQihT1AYgytqzZpD1atfyYqlT1h0lRpT7aRJ4NQpRvZGELVuo5Ua9jEJDIETQsNQyPBsUJMWGPnj//e+e72wNg4xElMR6ed'.
     1365            'ZNln3933dZ/f93f6yfB/sgmrHdDV1WXlPg8NDZUDScD8LFFFEZZlWYZhWMFg0Orq6sq/gDJAfFy1iiZy9OjrVnj4JzQ1rMWqfxm/'.
     1366            '309jYyNtbW0kEgnu3bvH4cOH88c/jqSKQl4/XGkd+eVtAN46up1LH92ktqYS++ZX8Pv9NDQ0sGnTJlKpFOFwmO7u7vy5IyMjeVRd'.
     1367            'XV1+WEOh0IrY4pDnq6wXX/sTiCJaMkFZdRNqxefoe7VtCSqXVDqdZnZ2ltraWkzTpKqqijt3JpFlG7dvj7NzZ1f++qFQyA3EClHL'.
     1368            'Ql743nFkhxPDtJAd5eTaYSVUfX09lZWVlJWVIUnSg7sVQMBCUcu4ceMGe/bsIRQK1QAzOcyykIM9P0KyudAyCWyqG8nhwqa4SkLt'.
     1369            '3r0bVVVxu924XC40TUOWZUQxe97CwgIdHR2LMHIxSCaVInVvFElxE0vMY1Pd2NUKJMWNTXHlUfF//4vETJCelwbpFm3MjP2dt37x'.
     1370            'AlN+PzU1NViWRSwW4+7du3g8HjweD4qi5EFAJzAExIpCANbooxhplfB0FJvTg6xWIqsVRVF6MopkU3FXPcnkJxGU0VEAdF2noqKC'.
     1371            'W3/8DpnqLjzep2lubsblcjE8PExHR8fboVDID9xYFpLBDpJF0jDQIncQpWlkm31FlFLtp9PfyuW/vYQj1kPSuRW/38+lj27S2Q7v'.
     1372            '/aWXUBVUffVNtm3blivVCEwsC5Eyc5iiApEpDEAXMqQdldhSiWVQHjJagud+8Fuexck/zv+K82dfoSbSCsDe75/km+4GVPd6+l5t'.
     1373            '4zJHcqVUYN2yEEtZQDCSJCueRAYsPY49HsFIZVG6p25JUumFafT4DKJN4amtT7Nz38sk5+5A70HMtEYyMkFiZhxzjQ/poXrLQrRU'.
     1374            'DFGEeFpAlkQkm4pRiCpIKodKzk0T/2QMh+piPjxKZPwiSkUtu/b9mNnJEWS7E8nhAmvpM60oJDkXJxqNozxRRUxPIesispBBlsXV'.
     1375            'UaKEFo8gzoaJhz8s2lOmrpUG+WBhJ9/60g+Z+fDXTAXfxllRjl1VkO0OFATsYhYliiK21ZKKhhHnFveUqSdKgwAEOp7F2v51vvw8'.
     1376            'XH7/N1wd/BlTweuUV65BdtgfoLTSkipsdD3tRi0VYpommUwGwzDwdT5HYEc3giAwcvH3jLz3BlPB67jWeZBEKYsSBWwpHZtNKo4q'.
     1377            'aHTDsJeeiGEYWJaFZVmYpommaRiGQdPnv0bb1m8gSRL/vPIOV979aR4lmAJ2p4qCgCxksNuKJ6VNpx4NYhgGpmkuQhmGQTqdxjAM'.
     1378            'qr2d7HtxEEEQuH1tkKvvvkF44tqDnrIcKJKAPf1g+LAUElq8dIiu60sApmnm93Pfzc7OYhgGrie+wFe++ztcLhcT1wf54PzPCU9c'.
     1379            'w7XWjWS3IdsdOAUBWZAxrRJnTQ6SG5bce2FCpmkughmGQSqVYm5uDtnj44sH38TtdhP6+Dwf//V4ttHXrkGURZJaic8RgHQ6jWma'.
     1380            'SJKUL5RLKNfIOczDKF3XSSaTRCIRhLJWntp3nGfWrSMxc5OLf3iNP4+68T9Ub9nF76lTpxgfHycajZJKpdA0LZ9GbjYV7hcDWZaF'.
     1381            'pmnMz88Ti8UYunSLmu1HFi2aVkxkaGjINTY2ttDb24vX6+XQoUNs3ryZ8vJyIDu1BUFYkkxhgxeiWlpaOHPmDE1NTdTX1xe98eWG'.
     1382            'JnF/9dQZCoXUYDA4AOD1ejlw4ACtra2Ul5fniwmCkEcUJiUIAoFAgL6+Pnw+H21tbfT39z8SxCS7hHsfWH9/8dL4MKqnp4eWlhac'.
     1383            'TmcekEvMNE2am5s5ceIEgUCA9vZ2Tp48ic/nY3j4UsmQHCYOjJHtpeBKqL1799Lc3IzT6UTXdRobGxkYGKC9vZ3W1tZ8Ko86NJ8a'.
     1384            'tXHjRo4dO8bp06fZsmULGzZsoL+/n0AggNfr5ezZs/8VpGTU5OSkc//+/acBfD4f1dXV7Nq1i4aGBs6dO4fP5+Pq1SuPBbIiyjTN'.
     1385            'RUnV1dUNXLhwAa/Xy44dO4jFYgBEo9FFF1r134BPuYlk16LrAYXsAlmtq6sbKDwoFAp9m+ykuP5ZQVZF3f8tCdwCov8LyHIoAANI'.
     1386            'AXf/A1TI0XCDh7OWAAAAAElFTkSuQmCC' ;
     1387
     1388        //==========================================================
     1389        // file_important.png
     1390        //==========================================================
     1391        $this->iBuiltinIcon[12][0]= 1785 ;
     1392        $this->iBuiltinIcon[12][1]=
     1393            'iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlz'.
     1394            'AAALDwAACw8BkvkDpQAAAAd0SU1FB9ECDAcjDeD3lKsAAAZ2SURBVHicrZhPaFzHHcc/897s7lutJCsr2VHsOHWMk0MPbsBUrcnF'.
     1395            'OFRdSo6FNhdB6SGHlpDmYtJCDyoxyKe6EBxKQkt7KKL0T6ABo0NbciqigtC6PhWKI2NFqqxdSd7V2/dmftPDvPd212t55dCBYfbN'.
     1396            'zpvfZ77z+/1mdhUjytWrV93Hf/24eD5z9gwiMlDjOKbb7dLtdhER2u02u7u73Lp1CxEZBw4AeZwdNQqkMd9wbziFGINJUt6rRbz5'.
     1397            '1ptUq1XK5TJBEAAUMHt7e+zu7gKwvLzMysoKwAng/uNg9CgQgFKlgg1DUJ67Vqtx6tQpZmdniaIIpRTOOZRSdDoddnZ2aLfbLC8v'.
     1398            's7S0xJUrV7ZGwQSj1PhhfRodVdDlMrpc5vup5Z2fvMPdu3fZ29vDWjvwztjYGPV6nVqtRqVS4dKlSywtLQFsAdOH2XwsCEApg3jl'.
     1399            'w98Rak2gvYjNZpNms0mSJDjnHgkDMDc3dySYQ0Ea8w139YUX0OUKulzyg7UmCEO+l1huvHuDra0t9vf3h1TJYSqVypFhHquIrlQI'.
     1400            'S5qv/uIDAC7/4bcEQYAKvK+0Wq1DVQGIoog7d+4cCeaRII35hrt+8SsEOkRlUaEyR0UpFIrXHxyMVKVUKnHv3r0jwRwaNelBjBjL'.
     1401            'Sz/7KYuLiwAsLi7y4z/9kY9e+TpkCuSqjI+Po7XuAWeKXLt2DWNMUZMkwRjDhQsXWFtbK6JpCCT3jfQgxomPtPX19YHWicM5x3c2'.
     1402            '73Pj3Ru8/aO3mZqaolKpoHVvyuvXr/Ppnf/Q7uzz380NPtu4y/qnG+ztd1hfX2dtbQ3gIvDnRyqSxl1UoPjyz98D4PTp0wPtq39Z'.
     1403            '4fdzLxegrVaLVqvF5OQkYRgWqpRKJZ77wvNsbW1RG5tgfKLOTH2G7Z1twqBQrgrMDvhInjfSOCY5iIv+hYWFgRZArEWsZWF941Bf'.
     1404            'SdMUgMnJCWpjVU4cn+HUyePM1Gc4+fRUPkzBI5w1jbukcczLv/5l0XfmzJmBFuCba38r/CRXpT+CrDUoZ0jjB4RYonJAOYRobJKT'.
     1405            'z5zgqfqxAbsFSH6mpHFM2qdGXh4VnoViD6mSJF2cTQeqDqBaKVHWmonJCWpZjhkC6anR5WsffTgwaHV1FaUUq6urA/2v3f5k4LnV'.
     1406            'arG9tUn3oI2YBCcWHYAxMVYs1qZEZY2SFB2aYZDGfMN9d7uJiWPSeFiNo5Rclc3NTXZbO6RpF7EJVixYA9agwwDnUiqlEPdQ3imi'.
     1407            'Jo27BGHIt/7x9yEjc3Nzh27Na7c/4TdffKl4bja3ae5MUIu0T/HOEIaOpJt4gwoSsVTK4SBIY77hFtY3ABBjBiZ90rKwvsH77/+K'.
     1408            't37wOhO1iPpTk4SBw1mLsz6CnKQ4l3qV+kE+t9XHlNZOk+bUJLVIE1VCcIJWQmJ6qjj30NbcXLkZMt8YPig+Z3n1G5fZ39/j/vY2'.
     1409            '9ckqZT2Ochbn0p4qNkU/dDfUADdXbh4HXgRO4zNdEU0XL1784PLly5w9e7Z4SazFOfGrEotDcOKrcoJPmrYIXf/Zop3QNd1skuGt'.
     1410            'cUAb2MgAxvHZTgFUq1Wmp6eZnZ0F8JlTjDduDThBnDeECEoJtbGIp6enqEblzCcEZ1PECU4yVRiOGgd0gc+AB0CZvkv1sWPHOHfu'.
     1411            'HOfPn8da41cpkkltEBEPJhYnBkTQJcdYVKGkgRxCfBsq5xXNgAa2Bn+hjTOgHEKBP8pzRUxykIH4ifLJRTJAl+UMBJzPHQ6bfe/f'.
     1412            'cWIzPxlUpD+zugzIZtVk1d8znBAqRxgoQuVQgSJQ3h9C5QhDRYgjUILCAzlnEdsHYTKfMTEBcP7F54YUGVmc2GLlIn6ve6v0ahSt'.
     1413            '8X25TzjJ+rIx1grKpQPWR4LkGVVsMgghvS0qjPdvm5OeceOTWA5Evo2mFzkjQfL7hZPUy5yvvF/uPFQL3+nbDmsLCEmT3sTmCTNr'.
     1414            'rogT6yFsOix3ftw7OwQhkvSU6CuinhCk0+kAkFoBazEEICHaHHiPVmU0gnUp4EAc1mYrF0EBVpwPi34VrBkwPxKk3W5ju/e5/c+d'.
     1415            'bGUHIAIuydTIE5zfc5Wr4lJcahHnHTP3CVGm78DrgY38N+DEibp7dmYKdAQmBh1hjEFjis+9CTWYGK21H6PxPyOI0DobYwzZF/z7'.
     1416            '7jadTvJtYG0kCD7lfwl49ijgT1gc0AH+dZSJA/xB+Mz/GSIvFoj/B7H1mAd8CO/zAAAAAElFTkSuQmCC' ;
     1417
     1418        $this->iLen = count($this->iBuiltinIcon);
    14681419    }
    14691420}
     
    14761427//===================================================
    14771428// CLASS IconImage
    1478 // Description: Holds properties for an icon image
     1429// Description: Holds properties for an icon image 
    14791430//===================================================
    14801431class IconImage {
     
    14841435    private $iScale=1.0;
    14851436
    1486     function __construct($aIcon,$aScale=1) {
    1487         GLOBAL $_gPredefIcons ;
    1488         if( is_string($aIcon) ) {
    1489             $this->iGDImage = Graph::LoadBkgImage('',$aIcon);
    1490         }
    1491         elseif( is_integer($aIcon) ) {
    1492             // Builtin image
    1493             $this->iGDImage = $_gPredefIcons->GetImg($aIcon);
    1494         }
    1495         else {
    1496             JpGraphError::RaiseL(6011);
    1497             //('Argument to IconImage must be string or integer');
    1498         }
    1499         $this->iScale = $aScale;
    1500         $this->iWidth = Image::GetWidth($this->iGDImage);
    1501         $this->iHeight = Image::GetHeight($this->iGDImage);
     1437    function IconImage($aIcon,$aScale=1) {
     1438        GLOBAL $_gPredefIcons ;
     1439        if( is_string($aIcon) ) {
     1440            $this->iGDImage = Graph::LoadBkgImage('',$aIcon);
     1441        }
     1442        elseif( is_integer($aIcon) ) {
     1443            // Builtin image
     1444            $this->iGDImage = $_gPredefIcons->GetImg($aIcon);
     1445        }
     1446        else {
     1447            JpGraphError::RaiseL(6011);
     1448//('Argument to IconImage must be string or integer');
     1449        }
     1450        $this->iScale = $aScale;
     1451        $this->iWidth = Image::GetWidth($this->iGDImage);
     1452        $this->iHeight = Image::GetHeight($this->iGDImage);
    15021453    }
    15031454
    15041455    function GetWidth() {
    1505         return round($this->iScale*$this->iWidth);
     1456        return round($this->iScale*$this->iWidth);
    15061457    }
    15071458
    15081459    function GetHeight() {
    1509         return round($this->iScale*$this->iHeight);
     1460        return round($this->iScale*$this->iHeight);
    15101461    }
    15111462
    15121463    function SetAlign($aX='left',$aY='center') {
    1513         $this->ixalign = $aX;
    1514         $this->iyalign = $aY;
     1464
     1465        $this->ixalign = $aX;
     1466        $this->iyalign = $aY;
     1467
    15151468    }
    15161469
    15171470    function Stroke($aImg,$x,$y) {
    15181471
    1519         if( $this->ixalign == 'right' ) {
    1520             $x -= $this->iWidth;
    1521         }
    1522         elseif( $this->ixalign == 'center' ) {
    1523             $x -= round($this->iWidth/2*$this->iScale);
    1524         }
    1525 
    1526         if( $this->iyalign == 'bottom' ) {
    1527             $y -= $this->iHeight;
    1528         }
    1529         elseif( $this->iyalign == 'center' ) {
    1530             $y -= round($this->iHeight/2*$this->iScale);
    1531         }
    1532 
    1533         $aImg->Copy($this->iGDImage,
    1534                                 $x,$y,0,0,
    1535                                 round($this->iWidth*$this->iScale),round($this->iHeight*$this->iScale),
    1536                                 $this->iWidth,$this->iHeight);
     1472        if( $this->ixalign == 'right' ) {
     1473            $x -= $this->iWidth;
     1474        }
     1475        elseif( $this->ixalign == 'center' ) {
     1476            $x -= round($this->iWidth/2*$this->iScale);
     1477        }
     1478
     1479        if( $this->iyalign == 'bottom' ) {
     1480            $y -= $this->iHeight;
     1481        }
     1482        elseif( $this->iyalign == 'center' ) {
     1483            $y -= round($this->iHeight/2*$this->iScale);
     1484        }
     1485
     1486        $aImg->Copy($this->iGDImage,
     1487                    $x,$y,0,0,
     1488                    round($this->iWidth*$this->iScale),round($this->iHeight*$this->iScale),
     1489                    $this->iWidth,$this->iHeight);
    15371490    }
    15381491}
     
    15471500    public $csimtarget='',$csimwintarget='',$csimalt='';
    15481501    private $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10;
    1549     private $iFontArray=array();
    15501502    private $iColor="black";
    15511503    private $iText="";
    15521504    private $iHAlign="left",$iVAlign="bottom";
    1553 
    1554     //---------------
    1555     // CONSTRUCTOR
    1556     function __construct($aTxt='') {
    1557         $this->iText = $aTxt;
    1558     }
    1559 
    1560     //---------------
    1561     // PUBLIC METHODS
     1505       
     1506//---------------
     1507// CONSTRUCTOR 
     1508    function TextProperty($aTxt='') {
     1509        $this->iText = $aTxt;
     1510    }           
     1511       
     1512//---------------
     1513// PUBLIC METHODS       
    15621514    function Set($aTxt) {
    1563         $this->iText = $aTxt;
     1515        $this->iText = $aTxt;
    15641516    }
    15651517
    15661518    function SetCSIMTarget($aTarget,$aAltText='',$aWinTarget='') {
    1567         if( is_string($aTarget) )
    1568         $aTarget = array($aTarget);
    1569         $this->csimtarget=$aTarget;
    1570 
    1571         if( is_string($aWinTarget) )
    1572         $aWinTarget = array($aWinTarget);
    1573         $this->csimwintarget=$aWinTarget;
    1574 
    1575         if( is_string($aAltText) )
    1576         $aAltText = array($aAltText);
     1519        if( is_string($aTarget) )
     1520            $aTarget = array($aTarget);
     1521        $this->csimtarget=$aTarget;
     1522
     1523        if( is_string($aWinTarget) )
     1524            $aWinTarget = array($aWinTarget);
     1525        $this->csimwintarget=$aWinTarget;
     1526
     1527        if( is_string($aAltText) )
     1528            $aAltText = array($aAltText);
    15771529        $this->csimalt=$aAltText;
    1578 
    1579     }
    1580 
     1530       
     1531    }
     1532   
    15811533    function SetCSIMAlt($aAltText) {
    1582         if( is_string($aAltText) )
    1583         $aAltText = array($aAltText);
     1534        if( is_string($aAltText) )
     1535            $aAltText = array($aAltText);
    15841536        $this->csimalt=$aAltText;
    15851537    }
     
    15871539    // Set text color
    15881540    function SetColor($aColor) {
    1589         $this->iColor = $aColor;
    1590     }
    1591 
     1541        $this->iColor = $aColor;
     1542    }
     1543       
    15921544    function HasTabs() {
    1593         if( is_string($this->iText) ) {
    1594             return substr_count($this->iText,"\t") > 0;
    1595         }
    1596         elseif( is_array($this->iText) ) {
    1597             return false;
    1598         }
    1599     }
    1600 
     1545        if( is_string($this->iText) ) {
     1546            return substr_count($this->iText,"\t") > 0;
     1547        }
     1548        elseif( is_array($this->iText) ) {
     1549            return false;
     1550        }
     1551    }
     1552       
    16011553    // Get number of tabs in string
    16021554    function GetNbrTabs() {
    1603         if( is_string($this->iText) ) {
    1604             return substr_count($this->iText,"\t") ;
    1605         }
    1606         else{
    1607             return 0;
    1608         }
    1609     }
    1610 
     1555        if( is_string($this->iText) ) {
     1556            return substr_count($this->iText,"\t") ;
     1557        }
     1558        else{
     1559            return 0;
     1560        }
     1561    }
     1562       
    16111563    // Set alignment
    16121564    function Align($aHAlign,$aVAlign="bottom") {
    1613         $this->iHAlign=$aHAlign;
    1614         $this->iVAlign=$aVAlign;
    1615     }
    1616 
     1565        $this->iHAlign=$aHAlign;
     1566        $this->iVAlign=$aVAlign;
     1567    }
     1568       
    16171569    // Synonym
    16181570    function SetAlign($aHAlign,$aVAlign="bottom") {
    1619         $this->iHAlign=$aHAlign;
    1620         $this->iVAlign=$aVAlign;
    1621     }
    1622 
     1571        $this->iHAlign=$aHAlign;
     1572        $this->iVAlign=$aVAlign;
     1573    }
     1574       
    16231575    // Specify font
    16241576    function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
    1625         $this->iFFamily = $aFFamily;
    1626         $this->iFStyle  = $aFStyle;
    1627         $this->iFSize  = $aFSize;
    1628     }
    1629 
    1630     function SetColumnFonts($aFontArray) {
    1631         if( !is_array($aFontArray) || count($aFontArray[0]) != 3 ) {
    1632             JpGraphError::RaiseL(6033);
    1633             // 'Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)'
    1634         }
    1635         $this->iFontArray = $aFontArray;
    1636     }
    1637 
     1577        $this->iFFamily = $aFFamily;
     1578        $this->iFStyle   = $aFStyle;
     1579        $this->iFSize    = $aFSize;
     1580    }
    16381581
    16391582    function IsColumns() {
    1640         return is_array($this->iText) ;
    1641     }
    1642 
     1583        return is_array($this->iText) ;
     1584    }
     1585       
    16431586    // Get width of text. If text contains several columns separated by
    1644     // tabs then return both the total width as well as an array with a
     1587    // tabs then return both the total width as well as an array with a 
    16451588    // width for each column.
    16461589    function GetWidth($aImg,$aUseTabs=false,$aTabExtraMargin=1.1) {
    1647         $extra_margin=4;
    1648         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1649         if( is_string($this->iText) ) {
    1650             if( strlen($this->iText) == 0 ) return 0;
    1651             $tmp = preg_split('/\t/',$this->iText);
    1652             if( count($tmp) <= 1 || !$aUseTabs ) {
    1653                 $w = $aImg->GetTextWidth($this->iText);
    1654                 return $w + 2*$extra_margin;
    1655             }
    1656             else {
    1657                 $tot=0;
    1658                 $n = count($tmp);
    1659                 for($i=0; $i < $n; ++$i) {
    1660                     $res[$i] = $aImg->GetTextWidth($tmp[$i]);
    1661                     $tot += $res[$i]*$aTabExtraMargin;
    1662                 }
    1663                 return array(round($tot),$res);
    1664             }
    1665         }
    1666         elseif( is_object($this->iText) ) {
    1667             // A single icon
    1668             return $this->iText->GetWidth()+2*$extra_margin;
    1669         }
    1670         elseif( is_array($this->iText) ) {
    1671             // Must be an array of texts. In this case we return the sum of the
    1672             // length + a fixed margin of 4 pixels on each text string
    1673             $n = count($this->iText);
    1674             $nf = count($this->iFontArray);
    1675             for( $i=0, $w=0; $i < $n; ++$i ) {
    1676                 if( $i < $nf ) {
    1677                     $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]);
    1678                 }
    1679                 else {
    1680                     $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1681                 }
    1682                 $tmp = $this->iText[$i];
    1683                 if( is_string($tmp) ) {
    1684                     $w += $aImg->GetTextWidth($tmp)+$extra_margin;
    1685                 }
    1686                 else {
    1687                     if( is_object($tmp) === false ) {
    1688                         JpGraphError::RaiseL(6012);
    1689                     }
    1690                     $w += $tmp->GetWidth()+$extra_margin;
    1691                 }
    1692             }
    1693             return $w;
    1694         }
    1695         else {
    1696             JpGraphError::RaiseL(6012);
    1697         }
     1590        $extra_margin=4;
     1591        $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1592        if( is_string($this->iText) ) {
     1593            if( strlen($this->iText) == 0 ) return 0;
     1594            $tmp = split("\t",$this->iText);
     1595            if( count($tmp) <= 1 || !$aUseTabs ) {
     1596                $w = $aImg->GetTextWidth($this->iText);
     1597                return $w + 2*$extra_margin;
     1598            }
     1599            else {
     1600                $tot=0;
     1601                $n = count($tmp);
     1602                for($i=0; $i < $n; ++$i) {
     1603                    $res[$i] = $aImg->GetTextWidth($tmp[$i]);
     1604                    $tot += $res[$i]*$aTabExtraMargin;
     1605                }
     1606                return array(round($tot),$res);
     1607            }
     1608        }
     1609        elseif( is_object($this->iText) ) {
     1610            // A single icon
     1611            return $this->iText->GetWidth()+2*$extra_margin;
     1612        }
     1613        elseif( is_array($this->iText) ) {
     1614            // Must be an array of texts. In this case we return the sum of the
     1615            // length + a fixed margin of 4 pixels on each text string
     1616            $n = count($this->iText);
     1617            for( $i=0, $w=0; $i < $n; ++$i ) {
     1618                $tmp = $this->iText[$i];
     1619                if( is_string($tmp) ) {
     1620                    $w += $aImg->GetTextWidth($tmp)+$extra_margin;
     1621                }
     1622                else {
     1623                    if( is_object($tmp) === false ) {
     1624                        JpGraphError::RaiseL(6012);
     1625                    }
     1626                    $w += $tmp->GetWidth()+$extra_margin;
     1627                }
     1628            }
     1629            return $w;
     1630        }
     1631        else {
     1632            JpGraphError::RaiseL(6012);
     1633        }
    16981634    }
    16991635
     
    17021638    // column as an array of one
    17031639    function GetColWidth($aImg,$aMargin=0) {
    1704         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1705         if( is_array($this->iText) ) {
    1706             $n = count($this->iText);
    1707             $nf = count($this->iFontArray);
    1708             for( $i=0, $w=array(); $i < $n; ++$i ) {
    1709                 $tmp = $this->iText[$i];
    1710                 if( is_string($tmp) ) {
    1711                     if( $i < $nf ) {
    1712                         $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]);
    1713                     }
    1714                     else {
    1715                         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1716                     }
    1717                     $w[$i] = $aImg->GetTextWidth($tmp)+$aMargin;
    1718                 }
    1719                 else {
    1720                     if( is_object($tmp) === false ) {
    1721                         JpGraphError::RaiseL(6012);
    1722                     }
    1723                     $w[$i] = $tmp->GetWidth()+$aMargin;
    1724                 }
    1725             }
    1726             return $w;
    1727         }
    1728         else {
    1729             return array($this->GetWidth($aImg));
    1730         }
    1731     }
    1732 
     1640        $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1641        if( is_array($this->iText) ) {
     1642            $n = count($this->iText);
     1643            for( $i=0, $w=array(); $i < $n; ++$i ) {
     1644                $tmp = $this->iText[$i];
     1645                if( is_string($tmp) ) {
     1646                    $w[$i] = $aImg->GetTextWidth($this->iText[$i])+$aMargin;
     1647                }
     1648                else {
     1649                    if( is_object($tmp) === false ) {
     1650                        JpGraphError::RaiseL(6012);
     1651                    }
     1652                    $w[$i] = $tmp->GetWidth()+$aMargin;
     1653                }
     1654            }
     1655            return $w; 
     1656        }
     1657        else {
     1658            return array($this->GetWidth($aImg));
     1659        }
     1660    }
     1661       
    17331662    // Get total height of text
    17341663    function GetHeight($aImg) {
    1735         $nf = count($this->iFontArray);
    1736         $maxheight = -1;
    1737 
    1738         if( $nf > 0 ) {
    1739             // We have to find out the largest font and take that one as the
    1740             // height of the row
    1741             for($i=0; $i < $nf; ++$i ) {
    1742                 $aImg->SetFont($this->iFontArray[$i][0],$this->iFontArray[$i][1],$this->iFontArray[$i][2]);
    1743                 $height = $aImg->GetFontHeight();
    1744                 $maxheight = max($height,$maxheight);
    1745             }
    1746         }
    1747 
    1748         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1749         $height = $aImg->GetFontHeight();
    1750         $maxheight = max($height,$maxheight);
    1751         return $maxheight;
    1752     }
    1753 
    1754     // Unhide/hide the text
     1664        $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1665        return $aImg->GetFontHeight();
     1666    }
     1667       
     1668    // Unhide/hide the text     
    17551669    function Show($aShow=true) {
    1756         $this->iShow=$aShow;
    1757     }
    1758 
     1670        $this->iShow=$aShow;
     1671    }
     1672       
    17591673    // Stroke text at (x,y) coordinates. If the text contains tabs then the
    17601674    // x parameter should be an array of positions to be used for each successive
    17611675    // tab mark. If no array is supplied then the tabs will be ignored.
    17621676    function Stroke($aImg,$aX,$aY) {
    1763         if( $this->iShow ) {
    1764             $aImg->SetColor($this->iColor);
    1765             $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1766             $aImg->SetTextAlign($this->iHAlign,$this->iVAlign);
    1767             if( $this->GetNbrTabs() < 1 ) {
    1768                 if( is_string($this->iText) ) {
    1769                     if( is_array($aX) ) $aX=$aX[0];
    1770                     if( is_array($aY) ) $aY=$aY[0];
    1771                     $aImg->StrokeText($aX,$aY,$this->iText);
    1772                 }
    1773                 elseif( is_array($this->iText) && ($n = count($this->iText)) > 0 ) {
    1774                     $ax = is_array($aX) ;
    1775                     $ay = is_array($aY) ;
    1776                     if( $ax && $ay ) {
    1777                         // Nothing; both are already arrays
    1778                     }
    1779                     elseif( $ax ) {
    1780                         $aY = array_fill(0,$n,$aY);
    1781                     }
    1782                     elseif( $ay ) {
    1783                         $aX = array_fill(0,$n,$aX);
    1784                     }
    1785                     else {
    1786                         $aX = array_fill(0,$n,$aX);
    1787                         $aY = array_fill(0,$n,$aY);
    1788                     }
    1789                     $n = min($n, count($aX) ) ;
    1790                     $n = min($n, count($aY) ) ;
    1791                     for($i=0; $i < $n; ++$i ) {
    1792                         $tmp = $this->iText[$i];
    1793                         if( is_object($tmp) ) {
    1794                             $tmp->Stroke($aImg,$aX[$i],$aY[$i]);
    1795                         }
    1796                         else {
    1797                             if( $i < count($this->iFontArray) ) {
    1798                                 $font = $this->iFontArray[$i];
    1799                                 $aImg->SetFont($font[0],$font[1],$font[2]);
    1800                             }
    1801                             else {
    1802                                 $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1803                             }
    1804                                 $aImg->StrokeText($aX[$i],$aY[$i],str_replace("\t"," ",$tmp));
    1805                         }
    1806                     }
    1807                 }
    1808             }
    1809             else {
    1810                 $tmp = preg_split('/\t/',$this->iText);
    1811                 $n = min(count($tmp),count($aX));
    1812                 for($i=0; $i < $n; ++$i) {
    1813                     if( $i < count($this->iFontArray) ) {
    1814                         $font = $this->iFontArray[$i];
    1815                         $aImg->SetFont($font[0],$font[1],$font[2]);
    1816                     }
    1817                     else {
    1818                         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1819                     }
    1820                     $aImg->StrokeText($aX[$i],$aY,$tmp[$i]);
    1821                 }
    1822             }
    1823         }
     1677        if( $this->iShow ) {
     1678            $aImg->SetColor($this->iColor);
     1679            $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1680            $aImg->SetTextAlign($this->iHAlign,$this->iVAlign);                 
     1681            if( $this->GetNbrTabs() <= 1 ) {
     1682                if( is_string($this->iText) ) {
     1683                    // Get rid of any "\t" characters and stroke string
     1684                    if( is_array($aX) ) $aX=$aX[0];
     1685                    if( is_array($aY) ) $aY=$aY[0];
     1686                    $aImg->StrokeText($aX,$aY,str_replace("\t"," ",$this->iText));
     1687                }
     1688                elseif( is_array($this->iText) && ($n = count($this->iText)) > 0 ) {
     1689                    $ax = is_array($aX) ;
     1690                    $ay = is_array($aY) ;
     1691                    if( $ax && $ay ) {
     1692                        // Nothing; both are already arrays
     1693                    }
     1694                    elseif( $ax ) {
     1695                        $aY = array_fill(0,$n,$aY);
     1696                    }
     1697                    elseif( $ay ) {
     1698                        $aX = array_fill(0,$n,$aX);
     1699                    }
     1700                    else {
     1701                        $aX = array_fill(0,$n,$aX);
     1702                        $aY = array_fill(0,$n,$aY);
     1703                    }
     1704                    $n = min($n, count($aX) ) ;
     1705                    $n = min($n, count($aY) ) ;
     1706                    for($i=0; $i < $n; ++$i ) {
     1707                        $tmp = $this->iText[$i];
     1708                        if( is_object($tmp) ) {
     1709                            $tmp->Stroke($aImg,$aX[$i],$aY[$i]);
     1710                        }
     1711                        else
     1712                            $aImg->StrokeText($aX[$i],$aY[$i],str_replace("\t"," ",$tmp));
     1713                    }
     1714                }
     1715            }
     1716            else {
     1717                $tmp = split("\t",$this->iText);
     1718                $n = min(count($tmp),count($aX));
     1719                for($i=0; $i < $n; ++$i) {
     1720                    $aImg->StrokeText($aX[$i],$aY,$tmp[$i]);
     1721                }       
     1722            }
     1723        }
    18241724    }
    18251725}
     
    18271727//===================================================
    18281728// CLASS HeaderProperty
    1829 // Description: Data encapsulating class to hold property
     1729// Description: Data encapsulating class to hold property 
    18301730// for each type of the scale headers
    18311731//===================================================
     
    18421742    public $iIntervall = 1;
    18431743
    1844     //---------------
    1845     // CONSTRUCTOR
    1846     function __construct() {
    1847         $this->grid = new LineProperty();
    1848     }
    1849 
    1850     //---------------
    1851     // PUBLIC METHODS
     1744//---------------
     1745// CONSTRUCTOR 
     1746    function HeaderProperty() {
     1747        $this->grid = new LineProperty();
     1748    }
     1749
     1750//---------------
     1751// PUBLIC METHODS               
    18521752    function Show($aShow=true) {
    1853         $this->iShowLabels = $aShow;
     1753        $this->iShowLabels = $aShow;
    18541754    }
    18551755
    18561756    function SetIntervall($aInt) {
    1857         $this->iIntervall = $aInt;
    1858     }
    1859 
    1860     function SetInterval($aInt) {
    1861         $this->iIntervall = $aInt;
     1757        $this->iIntervall = $aInt;
    18621758    }
    18631759
    18641760    function GetIntervall() {
    1865         return $this->iIntervall ;
    1866     }
    1867 
     1761        return $this->iIntervall ;
     1762    }
     1763       
    18681764    function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
    1869         $this->iFFamily = $aFFamily;
    1870         $this->iFStyle = $aFStyle;
    1871         $this->iFSize = $aFSize;
     1765        $this->iFFamily = $aFFamily;
     1766        $this->iFStyle  = $aFStyle;
     1767        $this->iFSize    = $aFSize;
    18721768    }
    18731769
    18741770    function SetFontColor($aColor) {
    1875         $this->iTextColor = $aColor;
    1876     }
    1877 
     1771        $this->iTextColor = $aColor;
     1772    }
     1773       
    18781774    function GetFontHeight($aImg) {
    1879         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1880         return $aImg->GetFontHeight();
     1775        $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1776        return $aImg->GetFontHeight();
    18811777    }
    18821778
    18831779    function GetFontWidth($aImg) {
    1884         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1885         return $aImg->GetFontWidth();
     1780        $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1781        return $aImg->GetFontWidth();
    18861782    }
    18871783
    18881784    function GetStrWidth($aImg,$aStr) {
    1889         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1890         return $aImg->GetTextWidth($aStr);
    1891     }
    1892 
     1785        $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1786        return $aImg->GetTextWidth($aStr);
     1787    }
     1788       
    18931789    function SetStyle($aStyle) {
    1894         $this->iStyle = $aStyle;
    1895     }
    1896 
     1790        $this->iStyle = $aStyle;
     1791    }
     1792       
    18971793    function SetBackgroundColor($aColor) {
    1898         $this->iBackgroundColor=$aColor;
     1794        $this->iBackgroundColor=$aColor;
    18991795    }
    19001796
    19011797    function SetFrameWeight($aWeight) {
    1902         $this->iFrameWeight=$aWeight;
     1798        $this->iFrameWeight=$aWeight;
    19031799    }
    19041800
    19051801    function SetFrameColor($aColor) {
    1906         $this->iFrameColor=$aColor;
    1907     }
    1908 
     1802        $this->iFrameColor=$aColor;
     1803    }
     1804       
    19091805    // Only used by day scale
    19101806    function SetWeekendColor($aColor) {
    1911         $this->iWeekendBackgroundColor=$aColor;
    1912     }
    1913 
     1807        $this->iWeekendBackgroundColor=$aColor;
     1808    }
     1809       
    19141810    // Only used by day scale
    19151811    function SetSundayFontColor($aColor) {
    1916         $this->iSundayTextColor=$aColor;
    1917     }
    1918 
     1812        $this->iSundayTextColor=$aColor;
     1813    }
     1814       
    19191815    function SetTitleVertMargin($aMargin) {
    1920         $this->iTitleVertMargin=$aMargin;
    1921     }
    1922 
     1816        $this->iTitleVertMargin=$aMargin;
     1817    }
     1818       
    19231819    function SetLabelFormatString($aStr) {
    1924         $this->iLabelFormStr=$aStr;
     1820        $this->iLabelFormStr=$aStr;
    19251821    }
    19261822
    19271823    function SetFormatString($aStr) {
    1928         $this->SetLabelFormatString($aStr);
     1824        $this->SetLabelFormatString($aStr);
    19291825    }
    19301826
     
    19481844    public $actinfo;
    19491845    public $iTopPlotMargin=10,$iBottomPlotMargin=15;
    1950     public $iVertLines=-1;
     1846    public $iVertLines=-1;     
    19511847    public $iVertHeaderSize=-1;
    19521848    // The width of the labels (defaults to the widest of all labels)
    1953     private $iLabelWidth;
     1849    private $iLabelWidth;       
    19541850    // Out image to stroke the scale to
    1955     private $iImg;
     1851    private $iImg;     
    19561852    private $iTableHeaderBackgroundColor="white",$iTableHeaderFrameColor="black";
    19571853    private $iTableHeaderFrameWeight=1;
     
    19601856    private $iVertLayout=GANTT_EVEN;
    19611857    private $iUsePlotWeekendBackground=true;
    1962     private $iWeekStart = 1; // Default to have weekends start on Monday
    1963 
    1964     //---------------
    1965     // CONSTRUCTOR
    1966     function __construct($aImg) {
    1967         $this->iImg = $aImg;
    1968         $this->iDateLocale = new DateLocale();
    1969 
    1970         $this->minute = new HeaderProperty();
    1971         $this->minute->SetIntervall(15);
    1972         $this->minute->SetLabelFormatString('i');
    1973         $this->minute->SetFont(FF_FONT0);
    1974         $this->minute->grid->SetColor("gray");
    1975 
    1976         $this->hour = new HeaderProperty();
    1977         $this->hour->SetFont(FF_FONT0);
    1978         $this->hour->SetIntervall(6);
    1979         $this->hour->SetStyle(HOURSTYLE_HM24);
    1980         $this->hour->SetLabelFormatString('H:i');
    1981         $this->hour->grid->SetColor("gray");
    1982 
    1983         $this->day = new HeaderProperty();
    1984         $this->day->grid->SetColor("gray");
    1985         $this->day->SetLabelFormatString('l');
    1986 
    1987         $this->week = new HeaderProperty();
    1988         $this->week->SetLabelFormatString("w%d");
    1989         $this->week->SetFont(FF_FONT1);
    1990 
    1991         $this->month = new HeaderProperty();
    1992         $this->month->SetFont(FF_FONT1,FS_BOLD);
    1993 
    1994         $this->year = new HeaderProperty();
    1995         $this->year->SetFont(FF_FONT1,FS_BOLD);
    1996 
    1997         $this->divider=new LineProperty();
    1998         $this->dividerh=new LineProperty();
    1999         $this->dividerh->SetWeight(2);
    2000         $this->divider->SetWeight(6);
    2001         $this->divider->SetColor('gray');
    2002         $this->divider->SetStyle('fancy');
    2003 
    2004         $this->tableTitle=new TextProperty();
    2005         $this->tableTitle->Show(false);
    2006         $this->actinfo = new GanttActivityInfo();
    2007     }
    2008 
    2009     //---------------
    2010     // PUBLIC METHODS
     1858    private $iWeekStart = 1;    // Default to have weekends start on Monday
     1859       
     1860//---------------
     1861// CONSTRUCTOR 
     1862    function GanttScale($aImg) {
     1863        $this->iImg = $aImg;           
     1864        $this->iDateLocale = new DateLocale();
     1865
     1866        $this->minute = new HeaderProperty();
     1867        $this->minute->SetIntervall(15);
     1868        $this->minute->SetLabelFormatString('i');
     1869        $this->minute->SetFont(FF_FONT0);
     1870        $this->minute->grid->SetColor("gray");
     1871
     1872        $this->hour = new HeaderProperty();
     1873        $this->hour->SetFont(FF_FONT0);
     1874        $this->hour->SetIntervall(6);
     1875        $this->hour->SetStyle(HOURSTYLE_HM24);
     1876        $this->hour->SetLabelFormatString('H:i');
     1877        $this->hour->grid->SetColor("gray");
     1878
     1879        $this->day = new HeaderProperty();
     1880        $this->day->grid->SetColor("gray");
     1881        $this->day->SetLabelFormatString('l');
     1882
     1883        $this->week = new HeaderProperty();
     1884        $this->week->SetLabelFormatString("w%d");
     1885        $this->week->SetFont(FF_FONT1);
     1886
     1887        $this->month = new HeaderProperty();
     1888        $this->month->SetFont(FF_FONT1,FS_BOLD);
     1889
     1890        $this->year = new HeaderProperty();
     1891        $this->year->SetFont(FF_FONT1,FS_BOLD);         
     1892               
     1893        $this->divider=new LineProperty();
     1894        $this->dividerh=new LineProperty();             
     1895        $this->dividerh->SetWeight(2);
     1896        $this->divider->SetWeight(6);
     1897        $this->divider->SetColor('gray');
     1898        $this->divider->SetStyle('fancy');
     1899
     1900        $this->tableTitle=new TextProperty();
     1901        $this->tableTitle->Show(false);
     1902        $this->actinfo = new GanttActivityInfo();
     1903    }
     1904       
     1905//---------------
     1906// PUBLIC METHODS       
    20111907    // Specify what headers should be visible
    20121908    function ShowHeaders($aFlg) {
    2013         $this->day->Show($aFlg & GANTT_HDAY);
    2014         $this->week->Show($aFlg & GANTT_HWEEK);
    2015         $this->month->Show($aFlg & GANTT_HMONTH);
    2016         $this->year->Show($aFlg & GANTT_HYEAR);
    2017         $this->hour->Show($aFlg & GANTT_HHOUR);
    2018         $this->minute->Show($aFlg & GANTT_HMIN);
    2019 
    2020         // Make some default settings of gridlines whihc makes sense
    2021         if( $aFlg & GANTT_HWEEK ) {
    2022             $this->month->grid->Show(false);
    2023             $this->year->grid->Show(false);
    2024         }
    2025         if( $aFlg & GANTT_HHOUR ) {
    2026             $this->day->grid->SetColor("black");
    2027         }
    2028     }
    2029 
     1909        $this->day->Show($aFlg & GANTT_HDAY);
     1910        $this->week->Show($aFlg & GANTT_HWEEK);
     1911        $this->month->Show($aFlg & GANTT_HMONTH);
     1912        $this->year->Show($aFlg & GANTT_HYEAR);
     1913        $this->hour->Show($aFlg & GANTT_HHOUR);
     1914        $this->minute->Show($aFlg & GANTT_HMIN);
     1915
     1916        // Make some default settings of gridlines whihc makes sense
     1917        if( $aFlg & GANTT_HWEEK ) {
     1918            $this->month->grid->Show(false);
     1919            $this->year->grid->Show(false);
     1920        }
     1921        if( $aFlg & GANTT_HHOUR ) {
     1922            $this->day->grid->SetColor("black");
     1923        }
     1924    }
     1925       
    20301926    // Should the weekend background stretch all the way down in the plotarea
    20311927    function UseWeekendBackground($aShow) {
    2032         $this->iUsePlotWeekendBackground = $aShow;
    2033     }
    2034 
     1928        $this->iUsePlotWeekendBackground = $aShow;
     1929    }
     1930       
    20351931    // Have a range been specified?
    20361932    function IsRangeSet() {
    2037         return $this->iStartDate!=-1 && $this->iEndDate!=-1;
    2038     }
    2039 
     1933        return $this->iStartDate!=-1 && $this->iEndDate!=-1;
     1934    }
     1935       
    20401936    // Should the layout be from top or even?
    20411937    function SetVertLayout($aLayout) {
    2042         $this->iVertLayout = $aLayout;
    2043     }
    2044 
     1938        $this->iVertLayout = $aLayout;
     1939    }
     1940       
    20451941    // Which locale should be used?
    20461942    function SetDateLocale($aLocale) {
    2047         $this->iDateLocale->Set($aLocale);
    2048     }
    2049 
     1943        $this->iDateLocale->Set($aLocale);
     1944    }
     1945       
    20501946    // Number of days we are showing
    20511947    function GetNumberOfDays() {
    2052         return round(($this->iEndDate-$this->iStartDate)/SECPERDAY);
    2053     }
    2054 
     1948        return round(($this->iEndDate-$this->iStartDate)/SECPERDAY);
     1949    }
     1950       
    20551951    // The width of the actual plot area
    20561952    function GetPlotWidth() {
    2057         $img=$this->iImg;
    2058         return $img->width - $img->left_margin - $img->right_margin;
     1953        $img=$this->iImg;
     1954        return $img->width - $img->left_margin - $img->right_margin;
    20591955    }
    20601956
     
    20631959    // widest title)
    20641960    function SetLabelWidth($aLabelWidth) {
    2065         $this->iLabelWidth=$aLabelWidth;
    2066     }
    2067 
    2068     // Which day should the week start?
    2069     // 0==Sun, 1==Monday, 2==Tuesday etc
     1961        $this->iLabelWidth=$aLabelWidth;
     1962    }
     1963
     1964        // Which day should the week start?
     1965        // 0==Sun, 1==Monday, 2==Tuesday etc
    20701966    function SetWeekStart($aStartDay) {
    2071         $this->iWeekStart = $aStartDay % 7;
    2072 
    2073         //Recalculate the startday since this will change the week start
    2074         $this->SetRange($this->iStartDate,$this->iEndDate);
     1967        $this->iWeekStart = $aStartDay % 7;
     1968       
     1969        //Recalculate the startday since this will change the week start
     1970        $this->SetRange($this->iStartDate,$this->iEndDate);
    20751971    }
    20761972
    20771973    // Do we show min scale?
    20781974    function IsDisplayMinute() {
    2079         return $this->minute->iShowLabels;
     1975        return $this->minute->iShowLabels;
    20801976    }
    20811977
    20821978    // Do we show day scale?
    20831979    function IsDisplayHour() {
    2084         return $this->hour->iShowLabels;
    2085     }
    2086 
    2087 
     1980        return $this->hour->iShowLabels;
     1981    }
     1982
     1983       
    20881984    // Do we show day scale?
    20891985    function IsDisplayDay() {
    2090         return $this->day->iShowLabels;
    2091     }
    2092 
     1986        return $this->day->iShowLabels;
     1987    }
     1988       
    20931989    // Do we show week scale?
    20941990    function IsDisplayWeek() {
    2095         return $this->week->iShowLabels;
    2096     }
    2097 
     1991        return $this->week->iShowLabels;
     1992    }
     1993       
    20981994    // Do we show month scale?
    20991995    function IsDisplayMonth() {
    2100         return $this->month->iShowLabels;
    2101     }
    2102 
     1996        return $this->month->iShowLabels;
     1997    }
     1998       
    21031999    // Do we show year scale?
    21042000    function IsDisplayYear() {
    2105         return $this->year->iShowLabels;
     2001        return $this->year->iShowLabels;
    21062002    }
    21072003
    21082004    // Specify spacing (in percent of bar height) between activity bars
    21092005    function SetVertSpacing($aSpacing) {
    2110         $this->iVertSpacing = $aSpacing;
     2006        $this->iVertSpacing = $aSpacing;
    21112007    }
    21122008
     
    21142010    // Always round to the nearest week boundary
    21152011    function SetRange($aMin,$aMax) {
    2116         $this->iStartDate = $this->NormalizeDate($aMin);
    2117         $this->iEndDate = $this->NormalizeDate($aMax);
     2012        $this->iStartDate = $this->NormalizeDate($aMin);
     2013        $this->iEndDate = $this->NormalizeDate($aMax); 
    21182014    }
    21192015
     
    21232019    function AdjustStartEndDay() {
    21242020
    2125         if( !($this->IsDisplayYear() ||$this->IsDisplayMonth() || $this->IsDisplayWeek()) ) {
    2126             // Don't adjust
    2127             return;
    2128         }
    2129 
    2130         // Get day in week for start and ending date (Sun==0)
    2131         $ds=strftime("%w",$this->iStartDate);
    2132         $de=strftime("%w",$this->iEndDate);
    2133 
    2134         // We want to start on iWeekStart day. But first we subtract a week
    2135         // if the startdate is "behind" the day the week start at.
    2136         // This way we ensure that the given start date is always included
    2137         // in the range. If we don't do this the nearest correct weekday in the week
    2138         // to start at might be later than the start date.
    2139         if( $ds < $this->iWeekStart )
    2140         $d = strtotime('-7 day',$this->iStartDate);
    2141         else
    2142         $d = $this->iStartDate;
    2143         $adjdate = strtotime(($this->iWeekStart-$ds).' day',$d /*$this->iStartDate*/ );
    2144         $this->iStartDate = $adjdate;
    2145 
    2146         // We want to end on the last day of the week
    2147         $preferredEndDay = ($this->iWeekStart+6)%7;
    2148         if( $preferredEndDay != $de ) {
    2149             // Solve equivalence eq:    $de + x ~ $preferredDay (mod 7)
    2150             $adj = (7+($preferredEndDay - $de)) % 7;
    2151             $adjdate = strtotime("+$adj day",$this->iEndDate);
    2152             $this->iEndDate = $adjdate;
    2153         }
    2154     }
    2155 
    2156     // Specify background for the table title area (upper left corner of the table)
     2021        if( !($this->IsDisplayYear() ||$this->IsDisplayMonth() || $this->IsDisplayWeek()) ) {
     2022            // Don't adjust
     2023            return;
     2024        }
     2025
     2026        // Get day in week for start and ending date (Sun==0)
     2027        $ds=strftime("%w",$this->iStartDate);
     2028        $de=strftime("%w",$this->iEndDate);     
     2029       
     2030        // We want to start on iWeekStart day. But first we subtract a week
     2031        // if the startdate is "behind" the day the week start at.
     2032        // This way we ensure that the given start date is always included
     2033        // in the range. If we don't do this the nearest correct weekday in the week
     2034        // to start at might be later than the start date.
     2035        if( $ds < $this->iWeekStart )
     2036            $d = strtotime('-7 day',$this->iStartDate);
     2037        else
     2038            $d = $this->iStartDate;
     2039        $adjdate = strtotime(($this->iWeekStart-$ds).' day',$d /*$this->iStartDate*/ );
     2040        $this->iStartDate = $adjdate;
     2041       
     2042        // We want to end on the last day of the week
     2043        $preferredEndDay = ($this->iWeekStart+6)%7;
     2044        if( $preferredEndDay != $de ) {
     2045            // Solve equivalence eq:    $de + x ~ $preferredDay (mod 7)
     2046            $adj = (7+($preferredEndDay - $de)) % 7;
     2047            $adjdate = strtotime("+$adj day",$this->iEndDate);
     2048            $this->iEndDate = $adjdate;
     2049        }       
     2050    }
     2051
     2052    // Specify background for the table title area (upper left corner of the table)     
    21572053    function SetTableTitleBackground($aColor) {
    2158         $this->iTableHeaderBackgroundColor = $aColor;
    2159     }
    2160 
    2161     ///////////////////////////////////////
    2162     // PRIVATE Methods
    2163 
     2054        $this->iTableHeaderBackgroundColor = $aColor;
     2055    }
     2056
     2057///////////////////////////////////////
     2058// PRIVATE Methods
     2059       
    21642060    // Determine the height of all the scale headers combined
    21652061    function GetHeaderHeight() {
    2166         $img=$this->iImg;
    2167         $height=1;
    2168         if( $this->minute->iShowLabels ) {
    2169             $height += $this->minute->GetFontHeight($img);
    2170             $height += $this->minute->iTitleVertMargin;
    2171         }
    2172         if( $this->hour->iShowLabels ) {
    2173             $height += $this->hour->GetFontHeight($img);
    2174             $height += $this->hour->iTitleVertMargin;
    2175         }
    2176         if( $this->day->iShowLabels ) {
    2177             $height += $this->day->GetFontHeight($img);
    2178             $height += $this->day->iTitleVertMargin;
    2179         }
    2180         if( $this->week->iShowLabels ) {
    2181             $height += $this->week->GetFontHeight($img);
    2182             $height += $this->week->iTitleVertMargin;
    2183         }
    2184         if( $this->month->iShowLabels ) {
    2185             $height += $this->month->GetFontHeight($img);
    2186             $height += $this->month->iTitleVertMargin;
    2187         }
    2188         if( $this->year->iShowLabels ) {
    2189             $height += $this->year->GetFontHeight($img);
    2190             $height += $this->year->iTitleVertMargin;
    2191         }
    2192         return $height;
    2193     }
    2194 
     2062        $img=$this->iImg;
     2063        $height=1;
     2064        if( $this->minute->iShowLabels ) {
     2065            $height += $this->minute->GetFontHeight($img);
     2066            $height += $this->minute->iTitleVertMargin;
     2067        }
     2068        if( $this->hour->iShowLabels ) {
     2069            $height += $this->hour->GetFontHeight($img);
     2070            $height += $this->hour->iTitleVertMargin;
     2071        }
     2072        if( $this->day->iShowLabels ) {
     2073            $height += $this->day->GetFontHeight($img);
     2074            $height += $this->day->iTitleVertMargin;
     2075        }
     2076        if( $this->week->iShowLabels ) {
     2077            $height += $this->week->GetFontHeight($img);
     2078            $height += $this->week->iTitleVertMargin;
     2079        }
     2080        if( $this->month->iShowLabels ) {
     2081            $height += $this->month->GetFontHeight($img);
     2082            $height += $this->month->iTitleVertMargin;
     2083        }
     2084        if( $this->year->iShowLabels ) {
     2085            $height += $this->year->GetFontHeight($img);
     2086            $height += $this->year->iTitleVertMargin;
     2087        }
     2088        return $height;
     2089    }
     2090       
    21952091    // Get width (in pixels) for a single day
    21962092    function GetDayWidth() {
    2197         return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays();
     2093        return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays();   
    21982094    }
    21992095
    22002096    // Get width (in pixels) for a single hour
    22012097    function GetHourWidth() {
    2202         return $this->GetDayWidth() / 24 ;
     2098        return $this->GetDayWidth() / 24 ;
    22032099    }
    22042100
    22052101    function GetMinuteWidth() {
    2206         return $this->GetHourWidth() / 60 ;
     2102        return $this->GetHourWidth() / 60 ;
    22072103    }
    22082104
    22092105    // Nuber of days in a year
    22102106    function GetNumDaysInYear($aYear) {
    2211         if( $this->IsLeap($aYear) )
    2212         return 366;
    2213         else
    2214         return 365;
    2215     }
    2216 
    2217     // Get week number
     2107        if( $this->IsLeap($aYear) )
     2108            return 366;
     2109        else
     2110            return 365;
     2111    }
     2112       
     2113    // Get week number 
    22182114    function GetWeekNbr($aDate,$aSunStart=true) {
    2219         // We can't use the internal strftime() since it gets the weeknumber
    2220         // wrong since it doesn't follow ISO on all systems since this is
    2221         // system linrary dependent.
    2222         // Even worse is that this works differently if we are on a Windows
    2223         // or UNIX box (it even differs between UNIX boxes how strftime()
    2224         // is natively implemented)
    2225         //
    2226         // Credit to Nicolas Hoizey <nhoizey@phpheaven.net> for this elegant
    2227         // version of Week Nbr calculation.
    2228 
    2229         $day = $this->NormalizeDate($aDate);
    2230         if( $aSunStart )
    2231         $day += 60*60*24;
    2232 
    2233         /*-------------------------------------------------------------------------
    2234          According to ISO-8601 :
    2235          "Week 01 of a year is per definition the first week that has the Thursday in this year,
    2236          which is equivalent to the week that contains the fourth day of January.
    2237          In other words, the first week of a new year is the week that has the majority of its
    2238          days in the new year."
    2239 
    2240          Be carefull, with PHP, -3 % 7 = -3, instead of 4 !!!
    2241 
    2242          day of year             = date("z", $day) + 1
    2243          offset to thursday      = 3 - (date("w", $day) + 6) % 7
    2244          first thursday of year  = 1 + (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $day)))) % 7
    2245          week number             = (thursday's day of year - first thursday's day of year) / 7 + 1
    2246          ---------------------------------------------------------------------------*/
    2247 
    2248         $thursday = $day + 60 * 60 * 24 * (3 - (date("w", $day) + 6) % 7);              // take week's thursday
    2249         $week = 1 + (date("z", $thursday) - (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $thursday)))) % 7) / 7;
    2250 
    2251         return $week;
    2252     }
    2253 
     2115        // We can't use the internal strftime() since it gets the weeknumber
     2116        // wrong since it doesn't follow ISO on all systems since this is
     2117        // system linrary dependent.
     2118        // Even worse is that this works differently if we are on a Windows
     2119        // or UNIX box (it even differs between UNIX boxes how strftime()
     2120        // is natively implemented)
     2121        //
     2122        // Credit to Nicolas Hoizey <nhoizey@phpheaven.net> for this elegant
     2123        // version of Week Nbr calculation.
     2124
     2125        $day = $this->NormalizeDate($aDate);
     2126        if( $aSunStart )
     2127            $day += 60*60*24;
     2128               
     2129        /*-------------------------------------------------------------------------
     2130          According to ISO-8601 :
     2131          "Week 01 of a year is per definition the first week that has the Thursday in this year,
     2132          which is equivalent to the week that contains the fourth day of January.
     2133          In other words, the first week of a new year is the week that has the majority of its
     2134          days in the new year."
     2135                 
     2136          Be carefull, with PHP, -3 % 7 = -3, instead of 4 !!!
     2137                 
     2138          day of year             = date("z", $day) + 1
     2139          offset to thursday      = 3 - (date("w", $day) + 6) % 7
     2140          first thursday of year  = 1 + (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $day)))) % 7
     2141          week number             = (thursday's day of year - first thursday's day of year) / 7 + 1
     2142          ---------------------------------------------------------------------------*/
     2143                 
     2144        $thursday = $day + 60 * 60 * 24 * (3 - (date("w", $day) + 6) % 7);              // take week's thursday
     2145        $week = 1 + (date("z", $thursday) - (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $thursday)))) % 7) / 7;
     2146                 
     2147        return $week;
     2148    }
     2149       
    22542150    // Is year a leap year?
    22552151    function IsLeap($aYear) {
    2256         // Is the year a leap year?
    2257         //$year = 0+date("Y",$aDate);
    2258         if( $aYear % 4 == 0)
    2259         if( !($aYear % 100 == 0) || ($aYear % 400 == 0) )
    2260         return true;
    2261         return false;
     2152        // Is the year a leap year?
     2153        //$year = 0+date("Y",$aDate);
     2154        if( $aYear % 4 == 0)
     2155            if( !($aYear % 100 == 0) || ($aYear % 400 == 0) )
     2156                return true;
     2157        return false;
    22622158    }
    22632159
    22642160    // Get current year
    22652161    function GetYear($aDate) {
    2266         return 0+Date("Y",$aDate);
    2267     }
    2268 
     2162        return 0+Date("Y",$aDate);
     2163    }
     2164       
    22692165    // Return number of days in a year
    22702166    function GetNumDaysInMonth($aMonth,$aYear) {
    2271         $days=array(31,28,31,30,31,30,31,31,30,31,30,31);
    2272         $daysl=array(31,29,31,30,31,30,31,31,30,31,30,31);
    2273         if( $this->IsLeap($aYear))
    2274         return $daysl[$aMonth];
    2275         else
    2276         return $days[$aMonth];
    2277     }
    2278 
     2167        $days=array(31,28,31,30,31,30,31,31,30,31,30,31);
     2168        $daysl=array(31,29,31,30,31,30,31,31,30,31,30,31);
     2169        if( $this->IsLeap($aYear))
     2170            return $daysl[$aMonth];
     2171        else
     2172            return $days[$aMonth];
     2173    }
     2174       
    22792175    // Get day in month
    22802176    function GetMonthDayNbr($aDate) {
    2281         return 0+strftime("%d",$aDate);
     2177        return 0+strftime("%d",$aDate);
    22822178    }
    22832179
    22842180    // Get day in year
    22852181    function GetYearDayNbr($aDate) {
    2286         return 0+strftime("%j",$aDate);
    2287     }
    2288 
     2182        return 0+strftime("%j",$aDate);
     2183    }
     2184       
    22892185    // Get month number
    22902186    function GetMonthNbr($aDate) {
    2291         return 0+strftime("%m",$aDate);
    2292     }
    2293 
    2294     // Translate a date to screen coordinates (horizontal scale)
     2187        return 0+strftime("%m",$aDate);
     2188    }
     2189       
     2190    // Translate a date to screen coordinates   (horizontal scale)
    22952191    function TranslateDate($aDate) {
    2296         //
    2297         // In order to handle the problem with Daylight savings time
    2298         // the scale written with equal number of seconds per day beginning
    2299         // with the start date. This means that we "cement" the state of
    2300         // DST as it is in the start date. If later the scale includes the
    2301         // switchover date (depends on the locale) we need to adjust back
    2302         // if the date we try to translate has a different DST status since
    2303         // we would otherwise be off by one hour.
    2304         $aDate = $this->NormalizeDate($aDate);
    2305         $tmp = localtime($aDate);
    2306         $cloc = $tmp[8];
    2307         $tmp = localtime($this->iStartDate);
    2308         $sloc = $tmp[8];
    2309         $offset = 0;
    2310         if( $sloc != $cloc) {
    2311             if( $sloc )
    2312             $offset = 3600;
    2313             else
    2314             $offset = -3600;
    2315         }
    2316         $img=$this->iImg;
    2317         return ($aDate-$this->iStartDate-$offset)/SECPERDAY*$this->GetDayWidth()+$img->left_margin+$this->iLabelWidth;;
    2318     }
    2319 
    2320     // Get screen coordinatesz for the vertical position for a bar
    2321     function TranslateVertPos($aPos,$atTop=false) {
    2322         $img=$this->iImg;
    2323         if( $aPos > $this->iVertLines )
    2324                 JpGraphError::RaiseL(6015,$aPos);
    2325         // 'Illegal vertical position %d'
    2326         if( $this->iVertLayout == GANTT_EVEN ) {
    2327             // Position the top bar at 1 vert spacing from the scale
    2328             $pos =  round($img->top_margin + $this->iVertHeaderSize +  ($aPos+1)*$this->iVertSpacing);
    2329         }
    2330         else {
    2331             // position the top bar at 1/2 a vert spacing from the scale
    2332             $pos = round($img->top_margin + $this->iVertHeaderSize  + $this->iTopPlotMargin + ($aPos+1)*$this->iVertSpacing);
    2333         }
    2334 
    2335         if( $atTop )
    2336             $pos -= $this->iVertSpacing;
    2337 
    2338         return $pos;
    2339     }
    2340 
     2192        //
     2193        // In order to handle the problem with Daylight savings time
     2194        // the scale written with equal number of seconds per day beginning
     2195        // with the start date. This means that we "cement" the state of
     2196        // DST as it is in the start date. If later the scale includes the
     2197        // switchover date (depends on the locale) we need to adjust back
     2198        // if the date we try to translate has a different DST status since
     2199        // we would otherwise be off by one hour.
     2200        $aDate = $this->NormalizeDate($aDate);
     2201        $tmp = localtime($aDate);
     2202        $cloc = $tmp[8];
     2203        $tmp = localtime($this->iStartDate);
     2204        $sloc = $tmp[8];
     2205        $offset = 0;
     2206        if( $sloc != $cloc) {
     2207            if( $sloc )
     2208                $offset = 3600;
     2209            else
     2210                $offset = -3600;
     2211        }
     2212        $img=$this->iImg;               
     2213        return ($aDate-$this->iStartDate-$offset)/SECPERDAY*$this->GetDayWidth()+$img->left_margin+$this->iLabelWidth;;
     2214    }
     2215
     2216    // Get screen coordinatesz for the vertical position for a bar             
     2217    function TranslateVertPos($aPos) {
     2218        $img=$this->iImg;
     2219        $ph=$this->iAvailableHeight;
     2220        if( $aPos > $this->iVertLines )
     2221            JpGraphError::RaiseL(6015,$aPos);
     2222// 'Illegal vertical position %d'
     2223        if( $this->iVertLayout == GANTT_EVEN ) {
     2224            // Position the top bar at 1 vert spacing from the scale
     2225            return round($img->top_margin + $this->iVertHeaderSize +  ($aPos+1)*$this->iVertSpacing);
     2226        }
     2227        else {
     2228            // position the top bar at 1/2 a vert spacing from the scale
     2229            return round($img->top_margin + $this->iVertHeaderSize  + $this->iTopPlotMargin + ($aPos+1)*$this->iVertSpacing);           
     2230        }
     2231    }
     2232       
    23412233    // What is the vertical spacing?
    23422234    function GetVertSpacing() {
    2343         return $this->iVertSpacing;
    2344     }
    2345 
     2235        return $this->iVertSpacing;
     2236    }
     2237                                       
    23462238    // Convert a date to timestamp
    23472239    function NormalizeDate($aDate) {
    2348         if( $aDate === false ) return false;
    2349         if( is_string($aDate) ) {
    2350             $t = strtotime($aDate);
    2351             if( $t === FALSE || $t === -1 ) {
    2352                 JpGraphError::RaiseL(6016,$aDate);
    2353                 //("Date string ($aDate) specified for Gantt activity can not be interpretated. Please make sure it is a valid time string, e.g. 2005-04-23 13:30");
    2354             }
    2355             return $t;
    2356         }
    2357         elseif( is_int($aDate) || is_float($aDate) )
    2358             return $aDate;
    2359         else
    2360             JpGraphError::RaiseL(6017,$aDate);
    2361         //Unknown date format in GanttScale ($aDate).");
    2362     }
    2363 
    2364 
     2240        if( $aDate === false ) return false;
     2241        if( is_string($aDate) ) {
     2242            $t = strtotime($aDate);
     2243            if( $t === FALSE || $t === -1 ) {
     2244                JpGraphError::RaiseL(6016,$aDate);
     2245//("Date string ($aDate) specified for Gantt activity can not be interpretated. Please make sure it is a valid time string, e.g. 2005-04-23 13:30");
     2246            }
     2247            return $t;
     2248        }
     2249        elseif( is_int($aDate) || is_float($aDate) )
     2250            return $aDate;
     2251        else
     2252            JpGraphError::RaiseL(6017,$aDate);
     2253//Unknown date format in GanttScale ($aDate).");
     2254    }
     2255
     2256   
    23652257    // Convert a time string to minutes
    23662258
    23672259    function TimeToMinutes($aTimeString) {
    2368         // Split in hours and minutes
    2369         $pos=strpos($aTimeString,':');
    2370         $minint=60;
    2371         if( $pos === false ) {
    2372             $hourint = $aTimeString;
    2373             $minint = 0;
    2374         }
    2375         else {
    2376             $hourint = floor(substr($aTimeString,0,$pos));
    2377             $minint = floor(substr($aTimeString,$pos+1));
    2378         }
    2379         $minint += 60 * $hourint;
    2380         return $minint;
    2381     }
    2382 
    2383     // Stroke the day scale (including gridlines)
     2260        // Split in hours and minutes
     2261        $pos=strpos($aTimeString,':');
     2262        $minint=60;
     2263        if( $pos === false ) {
     2264            $hourint = $aTimeString;
     2265            $minint = 0;
     2266        }
     2267        else {
     2268            $hourint = floor(substr($aTimeString,0,$pos));
     2269            $minint = floor(substr($aTimeString,$pos+1));
     2270        }
     2271        $minint += 60 * $hourint;
     2272        return $minint;
     2273    }
     2274
     2275    // Stroke the day scale (including gridlines)                       
    23842276    function StrokeMinutes($aYCoord,$getHeight=false) {
    2385         $img=$this->iImg;
    2386         $xt=$img->left_margin+$this->iLabelWidth;
    2387         $yt=$aYCoord+$img->top_margin;
    2388         if( $this->minute->iShowLabels ) {
    2389             $img->SetFont($this->minute->iFFamily,$this->minute->iFStyle,$this->minute->iFSize);
    2390             $yb = $yt + $img->GetFontHeight() +
    2391             $this->minute->iTitleVertMargin + $this->minute->iFrameWeight;
    2392             if( $getHeight ) {
    2393                 return $yb - $img->top_margin;
    2394             }
    2395             $xb = $img->width-$img->right_margin+1;
    2396             $img->SetColor($this->minute->iBackgroundColor);
    2397             $img->FilledRectangle($xt,$yt,$xb,$yb);
    2398 
    2399             $x = $xt;
    2400             $img->SetTextAlign("center");
    2401             $day = date('w',$this->iStartDate);
    2402             $minint = $this->minute->GetIntervall() ;
    2403 
    2404             if( 60 % $minint !== 0 ) {
     2277        $img=$this->iImg;       
     2278        $xt=$img->left_margin+$this->iLabelWidth;
     2279        $yt=$aYCoord+$img->top_margin;         
     2280        if( $this->minute->iShowLabels ) {
     2281            $img->SetFont($this->minute->iFFamily,$this->minute->iFStyle,$this->minute->iFSize);
     2282            $yb = $yt + $img->GetFontHeight() +
     2283                  $this->minute->iTitleVertMargin + $this->minute->iFrameWeight;
     2284            if( $getHeight ) {
     2285                return $yb - $img->top_margin;
     2286            }
     2287            $xb = $img->width-$img->right_margin+1;
     2288            $img->SetColor($this->minute->iBackgroundColor);
     2289            $img->FilledRectangle($xt,$yt,$xb,$yb);
     2290
     2291            $x = $xt;   
     2292            $img->SetTextAlign("center");
     2293            $day = date('w',$this->iStartDate);
     2294            $minint = $this->minute->GetIntervall() ;
     2295           
     2296            if( 60 % $minint !== 0 ) {
    24052297                JpGraphError::RaiseL(6018,$minint);
    2406                 //'Intervall for minutes must divide the hour evenly, e.g. 1,5,10,12,15,20,30 etc You have specified an intervall of '.$minint.' minutes.');
    2407             }
    2408 
    2409 
    2410             $n = 60 / $minint;
    2411             $datestamp = $this->iStartDate;
    2412             $width = $this->GetHourWidth() / $n ;
    2413             if( $width < 8 ) {
    2414                 // TO small width to draw minute scale
    2415                 JpGraphError::RaiseL(6019,$width);
    2416                 //('The available width ('.$width.') for minutes are to small for this scale to be displayed. Please use auto-sizing or increase the width of the graph.');
    2417             }
    2418 
    2419             $nh = ceil(24*60 / $this->TimeToMinutes($this->hour->GetIntervall()) );
    2420             $nd = $this->GetNumberOfDays();
    2421             // Convert to intervall to seconds
    2422             $minint *= 60;
    2423             for($j=0; $j < $nd; ++$j, $day += 1, $day %= 7) {
    2424                 for( $k=0; $k < $nh; ++$k ) {
    2425                     for($i=0; $i < $n ;++$i, $x+=$width, $datestamp += $minint ) {
    2426                         if( $day==6 || $day==0 ) {
    2427 
    2428                             $img->PushColor($this->day->iWeekendBackgroundColor);
    2429                             if( $this->iUsePlotWeekendBackground )
    2430                             $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin);
    2431                             else
    2432                             $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight);
    2433                             $img->PopColor();
    2434 
    2435                         }
    2436 
    2437                         if( $day==0 )
    2438                         $img->SetColor($this->day->iSundayTextColor);
    2439                         else
    2440                         $img->SetColor($this->day->iTextColor);
    2441 
    2442                         switch( $this->minute->iStyle ) {
    2443                             case MINUTESTYLE_CUSTOM:
    2444                                 $txt = date($this->minute->iLabelFormStr,$datestamp);
    2445                                 break;
    2446                             case MINUTESTYLE_MM:
    2447                             default:
    2448                                 // 15
    2449                                 $txt = date('i',$datestamp);
    2450                                 break;
    2451                         }
    2452                         $img->StrokeText(round($x+$width/2),round($yb-$this->minute->iTitleVertMargin),$txt);
    2453 
    2454                         // Fix a rounding problem the wrong way ..
    2455                         // If we also have hour scale then don't draw the firsta or last
    2456                         // gridline since that will be overwritten by the hour scale gridline if such exists.
    2457                         // However, due to the propagation of rounding of the 'x+=width' term in the loop
    2458                         // this might sometimes be one pixel of so we fix this by not drawing it.
    2459                         // The proper way to fix it would be to re-calculate the scale for each step and
    2460                         // not using the additive term.
    2461                         if( !(($i == $n || $i==0) && $this->hour->iShowLabels && $this->hour->grid->iShow) ) {
    2462                             $img->SetColor($this->minute->grid->iColor);
    2463                             $img->SetLineWeight($this->minute->grid->iWeight);
    2464                             $img->Line($x,$yt,$x,$yb);
    2465                             $this->minute->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
    2466                         }
    2467                     }
    2468                 }
    2469             }
    2470             $img->SetColor($this->minute->iFrameColor);
    2471             $img->SetLineWeight($this->minute->iFrameWeight);
    2472             $img->Rectangle($xt,$yt,$xb,$yb);
    2473             return $yb - $img->top_margin;
    2474         }
    2475         return $aYCoord;
    2476     }
    2477 
    2478     // Stroke the day scale (including gridlines)
     2298//'Intervall for minutes must divide the hour evenly, e.g. 1,5,10,12,15,20,30 etc You have specified an intervall of '.$minint.' minutes.');
     2299            }
     2300
     2301
     2302            $n = 60 / $minint;
     2303            $datestamp = $this->iStartDate;
     2304            $width = $this->GetHourWidth() / $n ;
     2305            if( $width < 8 ) {
     2306                // TO small width to draw minute scale
     2307                JpGraphError::RaiseL(6019,$width);
     2308//('The available width ('.$width.') for minutes are to small for this scale to be displayed. Please use auto-sizing or increase the width of the graph.');
     2309            }
     2310
     2311            $nh = ceil(24*60 / $this->TimeToMinutes($this->hour->GetIntervall()) );
     2312            $nd = $this->GetNumberOfDays();
     2313            // Convert to intervall to seconds
     2314            $minint *= 60;
     2315            for($j=0; $j < $nd; ++$j, $day += 1, $day %= 7) {
     2316                for( $k=0; $k < $nh; ++$k ) {
     2317                    for($i=0; $i < $n ;++$i, $x+=$width, $datestamp += $minint ) {   
     2318                        if( $day==6 || $day==0 ) {
     2319                       
     2320                            $img->PushColor($this->day->iWeekendBackgroundColor);
     2321                            if( $this->iUsePlotWeekendBackground )
     2322                                $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin);                                             
     2323                            else
     2324                                $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight);
     2325                            $img->PopColor();
     2326
     2327                        }
     2328
     2329                        if( $day==0 )
     2330                            $img->SetColor($this->day->iSundayTextColor);
     2331                        else
     2332                            $img->SetColor($this->day->iTextColor);
     2333
     2334                        switch( $this->minute->iStyle ) {
     2335                            case MINUTESTYLE_CUSTOM:
     2336                                $txt = date($this->minute->iLabelFormStr,$datestamp);
     2337                                break;
     2338                            case MINUTESTYLE_MM:
     2339                            default:
     2340                                // 15
     2341                                $txt = date('i',$datestamp);
     2342                                break;
     2343                        }
     2344                        $img->StrokeText(round($x+$width/2),round($yb-$this->minute->iTitleVertMargin),$txt);
     2345
     2346                        // FIXME: The rounding problem needs to be solved properly ...
     2347                        //
     2348                        // Fix a rounding problem the wrong way ..
     2349                        // If we also have hour scale then don't draw the firsta or last
     2350                        // gridline since that will be overwritten by the hour scale gridline if such exists.
     2351                        // However, due to the propagation of rounding of the 'x+=width' term in the loop
     2352                        // this might sometimes be one pixel of so we fix this by not drawing it.
     2353                        // The proper way to fix it would be to re-calculate the scale for each step and
     2354                        // not using the additive term.
     2355                        if( !(($i == $n || $i==0) && $this->hour->iShowLabels && $this->hour->grid->iShow) ) {
     2356                            $img->SetColor($this->minute->grid->iColor);
     2357                            $img->SetLineWeight($this->minute->grid->iWeight);
     2358                            $img->Line($x,$yt,$x,$yb);
     2359                            $this->minute->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
     2360                        }
     2361                    }           
     2362                }       
     2363            }
     2364            $img->SetColor($this->minute->iFrameColor);
     2365            $img->SetLineWeight($this->minute->iFrameWeight);
     2366            $img->Rectangle($xt,$yt,$xb,$yb);
     2367            return $yb - $img->top_margin;
     2368        }
     2369        return $aYCoord;
     2370    }
     2371
     2372    // Stroke the day scale (including gridlines)                       
    24792373    function StrokeHours($aYCoord,$getHeight=false) {
    2480         $img=$this->iImg;
    2481         $xt=$img->left_margin+$this->iLabelWidth;
    2482         $yt=$aYCoord+$img->top_margin;
    2483         if( $this->hour->iShowLabels ) {
    2484             $img->SetFont($this->hour->iFFamily,$this->hour->iFStyle,$this->hour->iFSize);
    2485             $yb = $yt + $img->GetFontHeight() +
    2486             $this->hour->iTitleVertMargin + $this->hour->iFrameWeight;
    2487             if( $getHeight ) {
    2488                 return $yb - $img->top_margin;
    2489             }
    2490             $xb = $img->width-$img->right_margin+1;
    2491             $img->SetColor($this->hour->iBackgroundColor);
    2492             $img->FilledRectangle($xt,$yt,$xb,$yb);
    2493 
    2494             $x = $xt;
    2495             $img->SetTextAlign("center");
    2496             $tmp = $this->hour->GetIntervall() ;
    2497             $minint = $this->TimeToMinutes($tmp);
    2498             if( 1440 % $minint !== 0 ) {
     2374        $img=$this->iImg;       
     2375        $xt=$img->left_margin+$this->iLabelWidth;
     2376        $yt=$aYCoord+$img->top_margin;         
     2377        if( $this->hour->iShowLabels ) {
     2378            $img->SetFont($this->hour->iFFamily,$this->hour->iFStyle,$this->hour->iFSize);
     2379            $yb = $yt + $img->GetFontHeight() +
     2380                  $this->hour->iTitleVertMargin + $this->hour->iFrameWeight;
     2381            if( $getHeight ) {
     2382                return $yb - $img->top_margin;
     2383            }
     2384            $xb = $img->width-$img->right_margin+1;
     2385            $img->SetColor($this->hour->iBackgroundColor);
     2386            $img->FilledRectangle($xt,$yt,$xb,$yb);
     2387
     2388            $x = $xt;   
     2389            $img->SetTextAlign("center");
     2390            $tmp = $this->hour->GetIntervall() ;
     2391            $minint = $this->TimeToMinutes($tmp);
     2392            if( 1440 % $minint !== 0 ) {
    24992393                JpGraphError::RaiseL(6020,$tmp);
    2500                 //('Intervall for hours must divide the day evenly, e.g. 0:30, 1:00, 1:30, 4:00 etc. You have specified an intervall of '.$tmp);
    2501             }
    2502 
    2503             $n = ceil(24*60 / $minint );
    2504             $datestamp = $this->iStartDate;
    2505             $day = date('w',$this->iStartDate);
    2506             $doback = !$this->minute->iShowLabels;
    2507             $width = $this->GetDayWidth() / $n ;
    2508             for($j=0; $j < $this->GetNumberOfDays(); ++$j, $day += 1,$day %= 7) {
    2509                 for($i=0; $i < $n ;++$i, $x+=$width) {
    2510                     if( $day==6 || $day==0 ) {
    2511 
    2512                         $img->PushColor($this->day->iWeekendBackgroundColor);
    2513                         if( $this->iUsePlotWeekendBackground && $doback )
    2514                         $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin);
    2515                         else
    2516                         $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight);
    2517                         $img->PopColor();
    2518 
    2519                     }
    2520 
    2521                     if( $day==0 )
    2522                     $img->SetColor($this->day->iSundayTextColor);
    2523                     else
    2524                     $img->SetColor($this->day->iTextColor);
    2525 
    2526                     switch( $this->hour->iStyle ) {
    2527                         case HOURSTYLE_HMAMPM:
    2528                             // 1:35pm
    2529                             $txt = date('g:ia',$datestamp);
    2530                             break;
    2531                         case HOURSTYLE_H24:
    2532                             // 13
    2533                             $txt = date('H',$datestamp);
    2534                             break;
    2535                         case HOURSTYLE_HAMPM:
    2536                             $txt = date('ga',$datestamp);
    2537                             break;
    2538                         case HOURSTYLE_CUSTOM:
    2539                             $txt = date($this->hour->iLabelFormStr,$datestamp);
    2540                             break;
    2541                         case HOURSTYLE_HM24:
    2542                         default:
    2543                             $txt = date('H:i',$datestamp);
    2544                             break;
    2545                     }
    2546                     $img->StrokeText(round($x+$width/2),round($yb-$this->hour->iTitleVertMargin),$txt);
    2547                     $img->SetColor($this->hour->grid->iColor);
    2548                     $img->SetLineWeight($this->hour->grid->iWeight);
    2549                     $img->Line($x,$yt,$x,$yb);
    2550                     $this->hour->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
    2551                     //$datestamp += $minint*60
    2552                     $datestamp = mktime(date('H',$datestamp),date('i',$datestamp)+$minint,0,
    2553                     date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp));
    2554 
    2555                 }
    2556             }
    2557             $img->SetColor($this->hour->iFrameColor);
    2558             $img->SetLineWeight($this->hour->iFrameWeight);
    2559             $img->Rectangle($xt,$yt,$xb,$yb);
    2560             return $yb - $img->top_margin;
    2561         }
    2562         return $aYCoord;
    2563     }
    2564 
    2565 
    2566     // Stroke the day scale (including gridlines)
     2394//('Intervall for hours must divide the day evenly, e.g. 0:30, 1:00, 1:30, 4:00 etc. You have specified an intervall of '.$tmp);
     2395            } 
     2396
     2397            $n = ceil(24*60 / $minint );
     2398            $datestamp = $this->iStartDate;
     2399            $day = date('w',$this->iStartDate);
     2400            $doback = !$this->minute->iShowLabels;
     2401            $width = $this->GetDayWidth() / $n ;
     2402            for($j=0; $j < $this->GetNumberOfDays(); ++$j, $day += 1,$day %= 7) {
     2403                for($i=0; $i < $n ;++$i, $x+=$width) {   
     2404                    if( $day==6 || $day==0 ) {
     2405                       
     2406                        $img->PushColor($this->day->iWeekendBackgroundColor);
     2407                        if( $this->iUsePlotWeekendBackground && $doback )
     2408                            $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$img->height-$img->bottom_margin);                                         
     2409                        else
     2410                            $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,$x+$width,$yb-$this->day->iFrameWeight);
     2411                        $img->PopColor();
     2412
     2413                    }
     2414
     2415                    if( $day==0 )
     2416                        $img->SetColor($this->day->iSundayTextColor);
     2417                    else
     2418                        $img->SetColor($this->day->iTextColor);
     2419
     2420                    switch( $this->hour->iStyle ) {
     2421                        case HOURSTYLE_HMAMPM:
     2422                            // 1:35pm
     2423                            $txt = date('g:ia',$datestamp);
     2424                            break;
     2425                        case HOURSTYLE_H24:
     2426                            // 13
     2427                            $txt = date('H',$datestamp);
     2428                            break;
     2429                        case HOURSTYLE_HAMPM:
     2430                            $txt = date('ga',$datestamp);
     2431                            break;
     2432                        case HOURSTYLE_CUSTOM:
     2433                            $txt = date($this->hour->iLabelFormStr,$datestamp);
     2434                            break;
     2435                        case HOURSTYLE_HM24:
     2436                        default:
     2437                            $txt = date('H:i',$datestamp);
     2438                            break;
     2439                    }
     2440                    $img->StrokeText(round($x+$width/2),round($yb-$this->hour->iTitleVertMargin),$txt);
     2441                    $img->SetColor($this->hour->grid->iColor);
     2442                    $img->SetLineWeight($this->hour->grid->iWeight);
     2443                    $img->Line($x,$yt,$x,$yb);
     2444                    $this->hour->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
     2445                    //$datestamp += $minint*60
     2446                    $datestamp = mktime(date('H',$datestamp),date('i',$datestamp)+$minint,0,
     2447                                        date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp));
     2448                   
     2449                }                       
     2450            }
     2451            $img->SetColor($this->hour->iFrameColor);
     2452            $img->SetLineWeight($this->hour->iFrameWeight);
     2453            $img->Rectangle($xt,$yt,$xb,$yb);
     2454            return $yb - $img->top_margin;
     2455        }
     2456        return $aYCoord;
     2457    }
     2458
     2459
     2460    // Stroke the day scale (including gridlines)                       
    25672461    function StrokeDays($aYCoord,$getHeight=false) {
    2568         $img=$this->iImg;
    2569         $daywidth=$this->GetDayWidth();
    2570         $xt=$img->left_margin+$this->iLabelWidth;
    2571         $yt=$aYCoord+$img->top_margin;
    2572         if( $this->day->iShowLabels ) {
    2573             $img->SetFont($this->day->iFFamily,$this->day->iFStyle,$this->day->iFSize);
    2574             $yb=$yt + $img->GetFontHeight() + $this->day->iTitleVertMargin + $this->day->iFrameWeight;
    2575             if( $getHeight ) {
    2576                 return $yb - $img->top_margin;
    2577             }
    2578             $xb=$img->width-$img->right_margin+1;
    2579             $img->SetColor($this->day->iBackgroundColor);
    2580             $img->FilledRectangle($xt,$yt,$xb,$yb);
    2581 
    2582             $x = $xt;
    2583             $img->SetTextAlign("center");
    2584             $day = date('w',$this->iStartDate);
    2585             $datestamp = $this->iStartDate;
    2586 
    2587             $doback = !($this->hour->iShowLabels || $this->minute->iShowLabels);
    2588 
    2589             setlocale(LC_TIME,$this->iDateLocale->iLocale);
    2590 
    2591             for($i=0; $i < $this->GetNumberOfDays(); ++$i, $x+=$daywidth, $day += 1,$day %= 7) {
    2592                 if( $day==6 || $day==0 ) {
    2593                     $img->SetColor($this->day->iWeekendBackgroundColor);
    2594                     if( $this->iUsePlotWeekendBackground && $doback)
    2595                         $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,
    2596                                               $x+$daywidth,$img->height-$img->bottom_margin);
    2597                     else
    2598                         $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,
    2599                     $x+$daywidth,$yb-$this->day->iFrameWeight);
    2600                 }
    2601 
    2602                 $mn = strftime('%m',$datestamp);
    2603                 if( $mn[0]=='0' )
    2604                     $mn = $mn[1];
    2605 
    2606                 switch( $this->day->iStyle ) {
    2607                     case DAYSTYLE_LONG:
    2608                         // "Monday"
    2609                         $txt = strftime('%A',$datestamp);
    2610                         break;
    2611                     case DAYSTYLE_SHORT:
    2612                         // "Mon"
    2613                         $txt = strftime('%a',$datestamp);
    2614                         break;
    2615                     case DAYSTYLE_SHORTDAYDATE1:
    2616                         // "Mon 23/6"
    2617                         $txt = strftime('%a %d/'.$mn,$datestamp);
    2618                         break;
    2619                     case DAYSTYLE_SHORTDAYDATE2:
    2620                         // "Mon 23 Jun"
    2621                         $txt = strftime('%a %d %b',$datestamp);
    2622                         break;
    2623                     case DAYSTYLE_SHORTDAYDATE3:
    2624                         // "Mon 23 Jun 2003"
    2625                         $txt = strftime('%a %d %b %Y',$datestamp);
    2626                         break;
    2627                     case DAYSTYLE_LONGDAYDATE1:
    2628                         // "Monday 23 Jun"
    2629                         $txt = strftime('%A %d %b',$datestamp);
    2630                         break;
    2631                     case DAYSTYLE_LONGDAYDATE2:
    2632                         // "Monday 23 Jun 2003"
    2633                         $txt = strftime('%A %d %b %Y',$datestamp);
    2634                         break;
    2635                     case DAYSTYLE_SHORTDATE1:
    2636                         // "23/6"
    2637                         $txt = strftime('%d/'.$mn,$datestamp);
    2638                         break;
    2639                     case DAYSTYLE_SHORTDATE2:
    2640                         // "23 Jun"
    2641                         $txt = strftime('%d %b',$datestamp);
    2642                         break;
    2643                     case DAYSTYLE_SHORTDATE3:
    2644                         // "Mon 23"
    2645                         $txt = strftime('%a %d',$datestamp);
    2646                         break;
    2647                     case DAYSTYLE_SHORTDATE4:
    2648                         // "23"
    2649                         $txt = strftime('%d',$datestamp);
    2650                         break;
    2651                     case DAYSTYLE_CUSTOM:
    2652                         // Custom format
    2653                         $txt = strftime($this->day->iLabelFormStr,$datestamp);
    2654                         break;
    2655                     case DAYSTYLE_ONELETTER:
    2656                     default:
    2657                         // "M"
    2658                         $txt = strftime('%A',$datestamp);
    2659                         $txt = strtoupper($txt[0]);
    2660                         break;
    2661                 }
    2662 
    2663                 if( $day==0 )
    2664                     $img->SetColor($this->day->iSundayTextColor);
    2665                 else
    2666                     $img->SetColor($this->day->iTextColor);
    2667                 $img->StrokeText(round($x+$daywidth/2+1),
    2668                 round($yb-$this->day->iTitleVertMargin),$txt);
    2669                 $img->SetColor($this->day->grid->iColor);
    2670                 $img->SetLineWeight($this->day->grid->iWeight);
    2671                 $img->Line($x,$yt,$x,$yb);
    2672                 $this->day->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
    2673                 $datestamp = mktime(0,0,0,date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp));
    2674                 //$datestamp += SECPERDAY;
    2675 
    2676             }
    2677             $img->SetColor($this->day->iFrameColor);
    2678             $img->SetLineWeight($this->day->iFrameWeight);
    2679             $img->Rectangle($xt,$yt,$xb,$yb);
    2680             return $yb - $img->top_margin;
    2681         }
    2682         return $aYCoord;
    2683     }
    2684 
     2462        $img=$this->iImg;       
     2463        $daywidth=$this->GetDayWidth();
     2464        $xt=$img->left_margin+$this->iLabelWidth;
     2465        $yt=$aYCoord+$img->top_margin;         
     2466        if( $this->day->iShowLabels ) {
     2467            $img->SetFont($this->day->iFFamily,$this->day->iFStyle,$this->day->iFSize);
     2468            $yb=$yt + $img->GetFontHeight() + $this->day->iTitleVertMargin + $this->day->iFrameWeight;
     2469            if( $getHeight ) {
     2470                return $yb - $img->top_margin;
     2471            }
     2472            $xb=$img->width-$img->right_margin+1;
     2473            $img->SetColor($this->day->iBackgroundColor);
     2474            $img->FilledRectangle($xt,$yt,$xb,$yb);
     2475
     2476            $x = $xt;   
     2477            $img->SetTextAlign("center");
     2478            $day = date('w',$this->iStartDate);
     2479            $datestamp = $this->iStartDate;
     2480           
     2481            $doback = !($this->hour->iShowLabels || $this->minute->iShowLabels);
     2482
     2483            setlocale(LC_TIME,$this->iDateLocale->iLocale);
     2484           
     2485            for($i=0; $i < $this->GetNumberOfDays(); ++$i, $x+=$daywidth, $day += 1,$day %= 7) {
     2486                if( $day==6 || $day==0 ) {
     2487                    $img->SetColor($this->day->iWeekendBackgroundColor);
     2488                    if( $this->iUsePlotWeekendBackground && $doback)
     2489                        $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,
     2490                                              $x+$daywidth,$img->height-$img->bottom_margin);   
     2491                    else
     2492                        $img->FilledRectangle($x,$yt+$this->day->iFrameWeight,
     2493                                              $x+$daywidth,$yb-$this->day->iFrameWeight);
     2494                }
     2495
     2496                $mn = strftime('%m',$datestamp);
     2497                if( $mn[0]=='0' )
     2498                    $mn = $mn[1];
     2499
     2500                switch( $this->day->iStyle ) {
     2501                    case DAYSTYLE_LONG:
     2502                        // "Monday"
     2503                        $txt = strftime('%A',$datestamp);
     2504                        break;
     2505                    case DAYSTYLE_SHORT:
     2506                        // "Mon"
     2507                        $txt = strftime('%a',$datestamp);
     2508                        break;
     2509                    case DAYSTYLE_SHORTDAYDATE1:
     2510                        // "Mon 23/6"
     2511                        $txt = strftime('%a %d/'.$mn,$datestamp);
     2512                        break;
     2513                    case DAYSTYLE_SHORTDAYDATE2:
     2514                        // "Mon 23 Jun"
     2515                        $txt = strftime('%a %d %b',$datestamp);
     2516                        break;
     2517                    case DAYSTYLE_SHORTDAYDATE3:
     2518                        // "Mon 23 Jun 2003"
     2519                        $txt = strftime('%a %d %b %Y',$datestamp);
     2520                        break;
     2521                    case DAYSTYLE_LONGDAYDATE1:
     2522                        // "Monday 23 Jun"
     2523                        $txt = strftime('%A %d %b',$datestamp);
     2524                        break;
     2525                    case DAYSTYLE_LONGDAYDATE2:
     2526                        // "Monday 23 Jun 2003"
     2527                        $txt = strftime('%A %d %b %Y',$datestamp);
     2528                        break;
     2529                    case DAYSTYLE_SHORTDATE1:
     2530                        // "23/6"
     2531                        $txt = strftime('%d/'.$mn,$datestamp);
     2532                        break;                 
     2533                    case DAYSTYLE_SHORTDATE2:
     2534                        // "23 Jun"
     2535                        $txt = strftime('%d %b',$datestamp);
     2536                        break;                 
     2537                    case DAYSTYLE_SHORTDATE3:
     2538                        // "Mon 23"
     2539                        $txt = strftime('%a %d',$datestamp);
     2540                        break; 
     2541                    case DAYSTYLE_SHORTDATE4:
     2542                        // "23"
     2543                        $txt = strftime('%d',$datestamp);
     2544                        break; 
     2545                    case DAYSTYLE_CUSTOM:
     2546                        // Custom format
     2547                        $txt = strftime($this->day->iLabelFormStr,$datestamp);
     2548                        break; 
     2549                    case DAYSTYLE_ONELETTER:
     2550                    default:
     2551                        // "M"
     2552                        $txt = strftime('%A',$datestamp);
     2553                        $txt = strtoupper($txt[0]);
     2554                        break;
     2555                }
     2556
     2557                if( $day==0 )
     2558                    $img->SetColor($this->day->iSundayTextColor);
     2559                else
     2560                    $img->SetColor($this->day->iTextColor);
     2561                $img->StrokeText(round($x+$daywidth/2+1),
     2562                                round($yb-$this->day->iTitleVertMargin),$txt);
     2563                $img->SetColor($this->day->grid->iColor);
     2564                $img->SetLineWeight($this->day->grid->iWeight);
     2565                $img->Line($x,$yt,$x,$yb);
     2566                $this->day->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
     2567                $datestamp = mktime(0,0,0,date("m",$datestamp),date("d",$datestamp)+1,date("Y",$datestamp));
     2568                //$datestamp += SECPERDAY;
     2569               
     2570            }                   
     2571            $img->SetColor($this->day->iFrameColor);
     2572            $img->SetLineWeight($this->day->iFrameWeight);
     2573            $img->Rectangle($xt,$yt,$xb,$yb);
     2574            return $yb - $img->top_margin;
     2575        }
     2576        return $aYCoord;
     2577    }
     2578       
    26852579    // Stroke week header and grid
    26862580    function StrokeWeeks($aYCoord,$getHeight=false) {
    2687         if( $this->week->iShowLabels ) {
    2688             $img=$this->iImg;
    2689             $yt=$aYCoord+$img->top_margin;
    2690             $img->SetFont($this->week->iFFamily,$this->week->iFStyle,$this->week->iFSize);
    2691             $yb=$yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight;
    2692 
    2693             if( $getHeight ) {
    2694                 return $yb - $img->top_margin;
    2695             }
    2696 
    2697             $xt=$img->left_margin+$this->iLabelWidth;
    2698             $weekwidth=$this->GetDayWidth()*7;
    2699             $wdays=$this->iDateLocale->GetDayAbb();
    2700             $xb=$img->width-$img->right_margin+1;
    2701             $week = $this->iStartDate;
    2702             $weeknbr=$this->GetWeekNbr($week);
    2703             $img->SetColor($this->week->iBackgroundColor);
    2704             $img->FilledRectangle($xt,$yt,$xb,$yb);
    2705             $img->SetColor($this->week->grid->iColor);
    2706             $x = $xt;
    2707             if( $this->week->iStyle==WEEKSTYLE_WNBR ) {
    2708                 $img->SetTextAlign("center");
    2709                 $txtOffset = $weekwidth/2+1;
    2710             }
    2711             elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY  ||
    2712                     $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 ||
    2713                     $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ||
    2714                     $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
    2715                 $img->SetTextAlign("left");
    2716                 $txtOffset = 3;
    2717             }
    2718             else {
    2719                 JpGraphError::RaiseL(6021);
    2720                 //("Unknown formatting style for week.");
    2721             }
    2722 
    2723             for($i=0; $i<$this->GetNumberOfDays()/7; ++$i, $x+=$weekwidth) {
    2724                 $img->PushColor($this->week->iTextColor);
    2725 
    2726                 if( $this->week->iStyle==WEEKSTYLE_WNBR )
    2727                     $txt = sprintf($this->week->iLabelFormStr,$weeknbr);
    2728                 elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY ||
    2729                         $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR )
    2730                     $txt = date("j/n",$week);
    2731                 elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 ||
    2732                         $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
    2733                     $monthnbr = date("n",$week)-1;
    2734                     $shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr);
    2735                     $txt = Date("j",$week)." ".$shortmonth;
    2736                 }
    2737 
    2738                 if( $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ||
    2739                 $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
    2740                     $w = sprintf($this->week->iLabelFormStr,$weeknbr);
    2741                     $txt .= ' '.$w;
    2742                 }
    2743 
    2744                 $img->StrokeText(round($x+$txtOffset),
    2745                 round($yb-$this->week->iTitleVertMargin),$txt);
    2746 
    2747                 $week = strtotime('+7 day',$week);
    2748                 $weeknbr = $this->GetWeekNbr($week);
    2749                 $img->PopColor();
    2750                 $img->SetLineWeight($this->week->grid->iWeight);
    2751                 $img->Line($x,$yt,$x,$yb);
    2752                 $this->week->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
    2753             }
    2754             $img->SetColor($this->week->iFrameColor);
    2755             $img->SetLineWeight($this->week->iFrameWeight);
    2756             $img->Rectangle($xt,$yt,$xb,$yb);
    2757             return $yb-$img->top_margin;
    2758         }
    2759         return $aYCoord;
    2760     }
    2761 
     2581        if( $this->week->iShowLabels ) {
     2582            $img=$this->iImg;   
     2583            $yt=$aYCoord+$img->top_margin;             
     2584            $img->SetFont($this->week->iFFamily,$this->week->iFStyle,$this->week->iFSize);
     2585            $yb=$yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight;
     2586
     2587            if( $getHeight ) {
     2588                return $yb - $img->top_margin; 
     2589            }
     2590
     2591            $xt=$img->left_margin+$this->iLabelWidth;
     2592            $weekwidth=$this->GetDayWidth()*7;
     2593            $wdays=$this->iDateLocale->GetDayAbb();     
     2594            $xb=$img->width-$img->right_margin+1;
     2595            $week = $this->iStartDate;
     2596            $weeknbr=$this->GetWeekNbr($week);
     2597            $img->SetColor($this->week->iBackgroundColor);
     2598            $img->FilledRectangle($xt,$yt,$xb,$yb);
     2599            $img->SetColor($this->week->grid->iColor);
     2600            $x = $xt;
     2601            if( $this->week->iStyle==WEEKSTYLE_WNBR ) {
     2602                $img->SetTextAlign("center");
     2603                $txtOffset = $weekwidth/2+1;
     2604            }
     2605            elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY  ||
     2606                    $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 ||
     2607                    $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ||
     2608                    $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
     2609                $img->SetTextAlign("left");
     2610                $txtOffset = 3;
     2611            }
     2612            else
     2613                JpGraphError::RaiseL(6021);
     2614//("Unknown formatting style for week.");
     2615                               
     2616            for($i=0; $i<$this->GetNumberOfDays()/7; ++$i, $x+=$weekwidth) {
     2617                $img->PushColor($this->week->iTextColor);
     2618                               
     2619                if( $this->week->iStyle==WEEKSTYLE_WNBR )
     2620                    $txt = sprintf($this->week->iLabelFormStr,$weeknbr);
     2621                elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY ||
     2622                        $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR )
     2623                    $txt = date("j/n",$week);
     2624                elseif( $this->week->iStyle==WEEKSTYLE_FIRSTDAY2 ||
     2625                        $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
     2626                    $monthnbr = date("n",$week)-1;
     2627                    $shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr);
     2628                    $txt = Date("j",$week)." ".$shortmonth;
     2629                }
     2630
     2631                if( $this->week->iStyle==WEEKSTYLE_FIRSTDAYWNBR ||
     2632                    $this->week->iStyle==WEEKSTYLE_FIRSTDAY2WNBR ) {
     2633                    $w = sprintf($this->week->iLabelFormStr,$weeknbr);
     2634                    $txt .= ' '.$w;
     2635                }
     2636                               
     2637                $img->StrokeText(round($x+$txtOffset),
     2638                                 round($yb-$this->week->iTitleVertMargin),$txt);
     2639                               
     2640                $week = strtotime('+7 day',$week);
     2641                $weeknbr = $this->GetWeekNbr($week);
     2642                $img->PopColor();       
     2643                $img->SetLineWeight($this->week->grid->iWeight);
     2644                $img->Line($x,$yt,$x,$yb);
     2645                $this->week->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
     2646            }                   
     2647            $img->SetColor($this->week->iFrameColor);
     2648            $img->SetLineWeight($this->week->iFrameWeight);
     2649            $img->Rectangle($xt,$yt,$xb,$yb);
     2650            return $yb-$img->top_margin;
     2651        }
     2652        return $aYCoord;
     2653    }   
     2654       
    27622655    // Format the mont scale header string
    27632656    function GetMonthLabel($aMonthNbr,$year) {
    2764         $sn = $this->iDateLocale->GetShortMonthName($aMonthNbr);
    2765         $ln = $this->iDateLocale->GetLongMonthName($aMonthNbr);
    2766         switch($this->month->iStyle) {
    2767             case MONTHSTYLE_SHORTNAME:
    2768                 $m=$sn;
    2769                 break;
    2770             case MONTHSTYLE_LONGNAME:
    2771                 $m=$ln;
    2772                 break;
    2773             case MONTHSTYLE_SHORTNAMEYEAR2:
    2774                 $m=$sn." '".substr("".$year,2);
    2775                 break;
    2776             case MONTHSTYLE_SHORTNAMEYEAR4:
    2777                 $m=$sn." ".$year;
    2778                 break;
    2779             case MONTHSTYLE_LONGNAMEYEAR2:
    2780                 $m=$ln." '".substr("".$year,2);
    2781                 break;
    2782             case MONTHSTYLE_LONGNAMEYEAR4:
    2783                 $m=$ln." ".$year;
    2784                 break;
    2785             case MONTHSTYLE_FIRSTLETTER:
    2786                 $m=$sn[0];
    2787                 break;
    2788         }
    2789         return $m;
    2790     }
    2791 
     2657        $sn = $this->iDateLocale->GetShortMonthName($aMonthNbr);
     2658        $ln = $this->iDateLocale->GetLongMonthName($aMonthNbr);
     2659        switch($this->month->iStyle) {
     2660            case MONTHSTYLE_SHORTNAME:
     2661                $m=$sn;
     2662                break;
     2663            case MONTHSTYLE_LONGNAME:
     2664                $m=$ln;
     2665                break;
     2666            case MONTHSTYLE_SHORTNAMEYEAR2:
     2667                $m=$sn." '".substr("".$year,2);
     2668                break;
     2669            case MONTHSTYLE_SHORTNAMEYEAR4:
     2670                $m=$sn." ".$year;
     2671                break;
     2672            case MONTHSTYLE_LONGNAMEYEAR2:
     2673                $m=$ln." '".substr("".$year,2);
     2674                break;
     2675            case MONTHSTYLE_LONGNAMEYEAR4:
     2676                $m=$ln." ".$year;
     2677                break;
     2678            case MONTHSTYLE_FIRSTLETTER:
     2679                $m=$sn[0];
     2680                break;
     2681        }
     2682        return $m;
     2683    }
     2684       
    27922685    // Stroke month scale and gridlines
    27932686    function StrokeMonths($aYCoord,$getHeight=false) {
    2794         if( $this->month->iShowLabels ) {
    2795             $img=$this->iImg;
    2796             $img->SetFont($this->month->iFFamily,$this->month->iFStyle,$this->month->iFSize);
    2797             $yt=$aYCoord+$img->top_margin;
    2798             $yb=$yt + $img->GetFontHeight() + $this->month->iTitleVertMargin + $this->month->iFrameWeight;
    2799             if( $getHeight ) {
    2800                 return $yb - $img->top_margin;
    2801             }
    2802             $monthnbr = $this->GetMonthNbr($this->iStartDate)-1;
    2803             $xt=$img->left_margin+$this->iLabelWidth;
    2804             $xb=$img->width-$img->right_margin+1;
    2805 
    2806             $img->SetColor($this->month->iBackgroundColor);
    2807             $img->FilledRectangle($xt,$yt,$xb,$yb);
    2808 
    2809             $img->SetLineWeight($this->month->grid->iWeight);
    2810             $img->SetColor($this->month->iTextColor);
    2811             $year = 0+strftime("%Y",$this->iStartDate);
    2812             $img->SetTextAlign("center");
    2813             if( $this->GetMonthNbr($this->iStartDate) == $this->GetMonthNbr($this->iEndDate)
    2814                 && $this->GetYear($this->iStartDate)==$this->GetYear($this->iEndDate) ) {
    2815                 $monthwidth=$this->GetDayWidth()*($this->GetMonthDayNbr($this->iEndDate) - $this->GetMonthDayNbr($this->iStartDate) + 1);
    2816             }
    2817             else {
    2818                 $monthwidth=$this->GetDayWidth()*($this->GetNumDaysInMonth($monthnbr,$year)-$this->GetMonthDayNbr($this->iStartDate)+1);
    2819             }
    2820             // Is it enough space to stroke the first month?
    2821             $monthName = $this->GetMonthLabel($monthnbr,$year);
    2822             if( $monthwidth >= 1.2*$img->GetTextWidth($monthName) ) {
    2823                 $img->SetColor($this->month->iTextColor);
    2824                 $img->StrokeText(round($xt+$monthwidth/2+1),
    2825                 round($yb-$this->month->iTitleVertMargin),
    2826                 $monthName);
    2827             }
    2828             $x = $xt + $monthwidth;
    2829             while( $x < $xb ) {
    2830                 $img->SetColor($this->month->grid->iColor);
    2831                 $img->Line($x,$yt,$x,$yb);
    2832                 $this->month->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
    2833                 $monthnbr++;
    2834                 if( $monthnbr==12 ) {
    2835                     $monthnbr=0;
    2836                     $year++;
    2837                 }
    2838                 $monthName = $this->GetMonthLabel($monthnbr,$year);
    2839                 $monthwidth=$this->GetDayWidth()*$this->GetNumDaysInMonth($monthnbr,$year);
    2840                 if( $x + $monthwidth < $xb )
    2841                     $w = $monthwidth;
    2842                 else
    2843                     $w = $xb-$x;
    2844                 if( $w >= 1.2*$img->GetTextWidth($monthName) ) {
    2845                     $img->SetColor($this->month->iTextColor);
    2846                     $img->StrokeText(round($x+$w/2+1),
    2847                     round($yb-$this->month->iTitleVertMargin),$monthName);
    2848                 }
    2849                 $x += $monthwidth;
    2850             }
    2851             $img->SetColor($this->month->iFrameColor);
    2852             $img->SetLineWeight($this->month->iFrameWeight);
    2853             $img->Rectangle($xt,$yt,$xb,$yb);
    2854             return $yb-$img->top_margin;
    2855         }
    2856         return $aYCoord;
     2687        if( $this->month->iShowLabels ) {
     2688            $img=$this->iImg;           
     2689            $img->SetFont($this->month->iFFamily,$this->month->iFStyle,$this->month->iFSize);
     2690            $yt=$aYCoord+$img->top_margin;             
     2691            $yb=$yt + $img->GetFontHeight() + $this->month->iTitleVertMargin + $this->month->iFrameWeight;
     2692            if( $getHeight ) {
     2693                return $yb - $img->top_margin; 
     2694            }
     2695            $monthnbr = $this->GetMonthNbr($this->iStartDate)-1;
     2696            $xt=$img->left_margin+$this->iLabelWidth;
     2697            $xb=$img->width-$img->right_margin+1;
     2698                       
     2699            $img->SetColor($this->month->iBackgroundColor);
     2700            $img->FilledRectangle($xt,$yt,$xb,$yb);
     2701
     2702            $img->SetLineWeight($this->month->grid->iWeight);
     2703            $img->SetColor($this->month->iTextColor);
     2704            $year = 0+strftime("%Y",$this->iStartDate);
     2705            $img->SetTextAlign("center");
     2706            if( $this->GetMonthNbr($this->iStartDate) == $this->GetMonthNbr($this->iEndDate) 
     2707                && $this->GetYear($this->iStartDate)==$this->GetYear($this->iEndDate) ) {
     2708                $monthwidth=$this->GetDayWidth()*($this->GetMonthDayNbr($this->iEndDate) - $this->GetMonthDayNbr($this->iStartDate) + 1);
     2709            }
     2710            else {
     2711                $monthwidth=$this->GetDayWidth()*($this->GetNumDaysInMonth($monthnbr,$year)-$this->GetMonthDayNbr($this->iStartDate)+1);
     2712            }
     2713            // Is it enough space to stroke the first month?
     2714            $monthName = $this->GetMonthLabel($monthnbr,$year);
     2715            if( $monthwidth >= 1.2*$img->GetTextWidth($monthName) ) {
     2716                $img->SetColor($this->month->iTextColor);                               
     2717                $img->StrokeText(round($xt+$monthwidth/2+1),
     2718                                round($yb-$this->month->iTitleVertMargin),
     2719                                $monthName);
     2720            }
     2721            $x = $xt + $monthwidth;
     2722            while( $x < $xb ) {
     2723                $img->SetColor($this->month->grid->iColor);                             
     2724                $img->Line($x,$yt,$x,$yb);
     2725                $this->month->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
     2726                $monthnbr++;
     2727                if( $monthnbr==12 ) {
     2728                    $monthnbr=0;
     2729                    $year++;
     2730                }
     2731                $monthName = $this->GetMonthLabel($monthnbr,$year);
     2732                $monthwidth=$this->GetDayWidth()*$this->GetNumDaysInMonth($monthnbr,$year);                             
     2733                if( $x + $monthwidth < $xb )
     2734                    $w = $monthwidth;
     2735                else
     2736                    $w = $xb-$x;
     2737                if( $w >= 1.2*$img->GetTextWidth($monthName) ) {
     2738                    $img->SetColor($this->month->iTextColor);                           
     2739                    $img->StrokeText(round($x+$w/2+1),
     2740                                     round($yb-$this->month->iTitleVertMargin),$monthName);
     2741                }
     2742                $x += $monthwidth;
     2743            }   
     2744            $img->SetColor($this->month->iFrameColor);
     2745            $img->SetLineWeight($this->month->iFrameWeight);
     2746            $img->Rectangle($xt,$yt,$xb,$yb);                   
     2747            return $yb-$img->top_margin;
     2748        }
     2749        return $aYCoord;
    28572750    }
    28582751
    28592752    // Stroke year scale and gridlines
    28602753    function StrokeYears($aYCoord,$getHeight=false) {
    2861         if( $this->year->iShowLabels ) {
    2862             $img=$this->iImg;
    2863             $yt=$aYCoord+$img->top_margin;
    2864             $img->SetFont($this->year->iFFamily,$this->year->iFStyle,$this->year->iFSize);
    2865             $yb=$yt + $img->GetFontHeight() + $this->year->iTitleVertMargin + $this->year->iFrameWeight;
    2866 
    2867             if( $getHeight ) {
    2868                 return $yb - $img->top_margin;
    2869             }
    2870 
    2871             $xb=$img->width-$img->right_margin+1;
    2872             $xt=$img->left_margin+$this->iLabelWidth;
    2873             $year = $this->GetYear($this->iStartDate);
    2874             $img->SetColor($this->year->iBackgroundColor);
    2875             $img->FilledRectangle($xt,$yt,$xb,$yb);
    2876             $img->SetLineWeight($this->year->grid->iWeight);
    2877             $img->SetTextAlign("center");
    2878             if( $year == $this->GetYear($this->iEndDate) )
    2879                 $yearwidth=$this->GetDayWidth()*($this->GetYearDayNbr($this->iEndDate)-$this->GetYearDayNbr($this->iStartDate)+1);
    2880             else
    2881                 $yearwidth=$this->GetDayWidth()*($this->GetNumDaysInYear($year)-$this->GetYearDayNbr($this->iStartDate)+1);
    2882 
    2883             // The space for a year must be at least 20% bigger than the actual text
    2884             // so we allow 10% margin on each side
    2885             if( $yearwidth >= 1.20*$img->GetTextWidth("".$year) ) {
    2886                 $img->SetColor($this->year->iTextColor);
    2887                 $img->StrokeText(round($xt+$yearwidth/2+1),
    2888                                 round($yb-$this->year->iTitleVertMargin),
    2889                                 $year);
    2890             }
    2891             $x = $xt + $yearwidth;
    2892             while( $x < $xb ) {
    2893                 $img->SetColor($this->year->grid->iColor);
    2894                 $img->Line($x,$yt,$x,$yb);
    2895                 $this->year->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
    2896                 $year += 1;
    2897                 $yearwidth=$this->GetDayWidth()*$this->GetNumDaysInYear($year);
    2898                 if( $x + $yearwidth < $xb )
    2899                     $w = $yearwidth;
    2900                 else
    2901                     $w = $xb-$x;
    2902                 if( $w >= 1.2*$img->GetTextWidth("".$year) ) {
    2903                     $img->SetColor($this->year->iTextColor);
    2904                     $img->StrokeText(round($x+$w/2+1),
    2905                                      round($yb-$this->year->iTitleVertMargin),
    2906                                      $year);
    2907                 }
    2908                 $x += $yearwidth;
    2909             }
    2910             $img->SetColor($this->year->iFrameColor);
    2911             $img->SetLineWeight($this->year->iFrameWeight);
    2912             $img->Rectangle($xt,$yt,$xb,$yb);
    2913             return $yb-$img->top_margin;
    2914         }
    2915         return $aYCoord;
    2916     }
    2917 
     2754        if( $this->year->iShowLabels ) {
     2755            $img=$this->iImg;   
     2756            $yt=$aYCoord+$img->top_margin;             
     2757            $img->SetFont($this->year->iFFamily,$this->year->iFStyle,$this->year->iFSize);
     2758            $yb=$yt + $img->GetFontHeight() + $this->year->iTitleVertMargin + $this->year->iFrameWeight;
     2759
     2760            if( $getHeight ) {
     2761                return $yb - $img->top_margin; 
     2762            }
     2763
     2764            $xb=$img->width-$img->right_margin+1;
     2765            $xt=$img->left_margin+$this->iLabelWidth;
     2766            $year = $this->GetYear($this->iStartDate);                 
     2767            $img->SetColor($this->year->iBackgroundColor);
     2768            $img->FilledRectangle($xt,$yt,$xb,$yb);
     2769            $img->SetLineWeight($this->year->grid->iWeight);
     2770            $img->SetTextAlign("center");
     2771            if( $year == $this->GetYear($this->iEndDate) )
     2772                $yearwidth=$this->GetDayWidth()*($this->GetYearDayNbr($this->iEndDate)-$this->GetYearDayNbr($this->iStartDate)+1);
     2773            else
     2774                $yearwidth=$this->GetDayWidth()*($this->GetNumDaysInYear($year)-$this->GetYearDayNbr($this->iStartDate)+1);
     2775                       
     2776            // The space for a year must be at least 20% bigger than the actual text
     2777            // so we allow 10% margin on each side
     2778            if( $yearwidth >= 1.20*$img->GetTextWidth("".$year) ) {
     2779                $img->SetColor($this->year->iTextColor);                               
     2780                $img->StrokeText(round($xt+$yearwidth/2+1),
     2781                                round($yb-$this->year->iTitleVertMargin),
     2782                                $year);
     2783            }
     2784            $x = $xt + $yearwidth;
     2785            while( $x < $xb ) {
     2786                $img->SetColor($this->year->grid->iColor);                             
     2787                $img->Line($x,$yt,$x,$yb);
     2788                $this->year->grid->Stroke($img,$x,$yb,$x,$img->height-$img->bottom_margin);
     2789                $year += 1;
     2790                $yearwidth=$this->GetDayWidth()*$this->GetNumDaysInYear($year);                         
     2791                if( $x + $yearwidth < $xb )
     2792                    $w = $yearwidth;
     2793                else
     2794                    $w = $xb-$x;
     2795                if( $w >= 1.2*$img->GetTextWidth("".$year) ) {
     2796                    $img->SetColor($this->year->iTextColor);
     2797                    $img->StrokeText(round($x+$w/2+1),
     2798                                     round($yb-$this->year->iTitleVertMargin),
     2799                                     $year);
     2800                }
     2801                $x += $yearwidth;
     2802            }
     2803            $img->SetColor($this->year->iFrameColor);
     2804            $img->SetLineWeight($this->year->iFrameWeight);
     2805            $img->Rectangle($xt,$yt,$xb,$yb);                   
     2806            return $yb-$img->top_margin;
     2807        }
     2808        return $aYCoord;
     2809    }
     2810       
    29182811    // Stroke table title (upper left corner)
    29192812    function StrokeTableHeaders($aYBottom) {
    2920         $img=$this->iImg;
    2921         $xt=$img->left_margin;
    2922         $yt=$img->top_margin;
    2923         $xb=$xt+$this->iLabelWidth;
    2924         $yb=$aYBottom+$img->top_margin;
    2925 
    2926         if( $this->tableTitle->iShow ) {
    2927             $img->SetColor($this->iTableHeaderBackgroundColor);
    2928             $img->FilledRectangle($xt,$yt,$xb,$yb);
    2929             $this->tableTitle->Align("center","top");
    2930             $this->tableTitle->Stroke($img,$xt+($xb-$xt)/2+1,$yt+2);
    2931             $img->SetColor($this->iTableHeaderFrameColor);
    2932             $img->SetLineWeight($this->iTableHeaderFrameWeight);
    2933             $img->Rectangle($xt,$yt,$xb,$yb);
    2934         }
    2935 
    2936         $this->actinfo->Stroke($img,$xt,$yt,$xb,$yb,$this->tableTitle->iShow);
    2937 
    2938 
    2939         // Draw the horizontal dividing line
    2940         $this->dividerh->Stroke($img,$xt,$yb,$img->width-$img->right_margin,$yb);
    2941 
    2942         // Draw the vertical dividing line
    2943         // We do the width "manually" since we want the line only to grow
    2944         // to the left
    2945         $fancy = $this->divider->iStyle == 'fancy' ;
    2946         if( $fancy ) {
    2947             $this->divider->iStyle = 'solid';
    2948         }
    2949 
    2950         $tmp = $this->divider->iWeight;
    2951         $this->divider->iWeight=1;
    2952         $y = $img->height-$img->bottom_margin;
    2953         for($i=0; $i < $tmp; ++$i ) {
    2954             $this->divider->Stroke($img,$xb-$i,$yt,$xb-$i,$y);
    2955         }
    2956 
    2957         // Should we draw "fancy" divider
    2958         if( $fancy ) {
    2959             $img->SetLineWeight(1);
    2960             $img->SetColor($this->iTableHeaderFrameColor);
    2961             $img->Line($xb,$yt,$xb,$y);
    2962             $img->Line($xb-$tmp+1,$yt,$xb-$tmp+1,$y);
    2963             $img->SetColor('white');
    2964             $img->Line($xb-$tmp+2,$yt,$xb-$tmp+2,$y);
    2965         }
     2813        $img=$this->iImg;
     2814        $xt=$img->left_margin;
     2815        $yt=$img->top_margin;
     2816        $xb=$xt+$this->iLabelWidth;
     2817        $yb=$aYBottom+$img->top_margin;
     2818
     2819        if( $this->tableTitle->iShow ) {
     2820            $img->SetColor($this->iTableHeaderBackgroundColor);
     2821            $img->FilledRectangle($xt,$yt,$xb,$yb);
     2822            $this->tableTitle->Align("center","top");
     2823            $this->tableTitle->Stroke($img,$xt+($xb-$xt)/2+1,$yt+2);           
     2824            $img->SetColor($this->iTableHeaderFrameColor);
     2825            $img->SetLineWeight($this->iTableHeaderFrameWeight);
     2826            $img->Rectangle($xt,$yt,$xb,$yb);
     2827        }
     2828
     2829        $this->actinfo->Stroke($img,$xt,$yt,$xb,$yb,$this->tableTitle->iShow);
     2830
     2831
     2832        // Draw the horizontal dividing line           
     2833        $this->dividerh->Stroke($img,$xt,$yb,$img->width-$img->right_margin,$yb);               
     2834               
     2835        // Draw the vertical dividing line
     2836        // We do the width "manually" since we want the line only to grow
     2837        // to the left
     2838        $fancy = $this->divider->iStyle == 'fancy' ;
     2839        if( $fancy ) {
     2840            $this->divider->iStyle = 'solid';
     2841        }
     2842
     2843        $tmp = $this->divider->iWeight;
     2844        $this->divider->iWeight=1;
     2845        $y = $img->height-$img->bottom_margin;
     2846        for($i=0; $i < $tmp; ++$i ) {
     2847            $this->divider->Stroke($img,$xb-$i,$yt,$xb-$i,$y);
     2848        }
     2849
     2850        // Should we draw "fancy" divider
     2851        if( $fancy ) {
     2852            $img->SetLineWeight(1);
     2853            $img->SetColor($this->iTableHeaderFrameColor);
     2854            $img->Line($xb,$yt,$xb,$y);
     2855            $img->Line($xb-$tmp+1,$yt,$xb-$tmp+1,$y);
     2856            $img->SetColor('white');
     2857            $img->Line($xb-$tmp+2,$yt,$xb-$tmp+2,$y);
     2858        }
    29662859    }
    29672860
    29682861    // Main entry point to stroke scale
    29692862    function Stroke() {
    2970         if( !$this->IsRangeSet() ) {
    2971                 JpGraphError::RaiseL(6022);
    2972                 //("Gantt scale has not been specified.");
    2973         }
    2974         $img=$this->iImg;
    2975 
    2976         // If minutes are displayed then hour interval must be 1
    2977         if( $this->IsDisplayMinute() && $this->hour->GetIntervall() > 1 ) {
    2978             JpGraphError::RaiseL(6023);
    2979             //('If you display both hour and minutes the hour intervall must be 1 (Otherwise it doesn\' make sense to display minutes).');
    2980         }
    2981 
    2982         // Stroke all headers. As argument we supply the offset from the
    2983         // top which depends on any previous headers
    2984 
    2985         // First find out the height of each header
    2986         $offy=$this->StrokeYears(0,true);
    2987         $offm=$this->StrokeMonths($offy,true);
    2988         $offw=$this->StrokeWeeks($offm,true);
    2989         $offd=$this->StrokeDays($offw,true);
    2990         $offh=$this->StrokeHours($offd,true);
    2991         $offmin=$this->StrokeMinutes($offh,true);
    2992 
    2993 
    2994         // ... then we can stroke them in the "backwards order to ensure that
    2995         // the larger scale gridlines is stroked over the smaller scale gridline
    2996         $this->StrokeMinutes($offh);
    2997         $this->StrokeHours($offd);
    2998         $this->StrokeDays($offw);
    2999         $this->StrokeWeeks($offm);
    3000         $this->StrokeMonths($offy);
    3001         $this->StrokeYears(0);
    3002 
    3003         // Now when we now the oaverall size of the scale headers
    3004         // we can stroke the overall table headers
    3005         $this->StrokeTableHeaders($offmin);
    3006 
    3007         // Now we can calculate the correct scaling factor for each vertical position
    3008         $this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd;
    3009 
    3010         $this->iVertHeaderSize = $offmin;
    3011         if( $this->iVertSpacing == -1 )
    3012                 $this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines;
    3013     }
     2863        if( !$this->IsRangeSet() )
     2864            JpGraphError::RaiseL(6022);
     2865//("Gantt scale has not been specified.");
     2866        $img=$this->iImg;
     2867
     2868        // If minutes are displayed then hour interval must be 1
     2869        if( $this->IsDisplayMinute() && $this->hour->GetIntervall() > 1 ) {
     2870            JpGraphError::RaiseL(6023);
     2871//('If you display both hour and minutes the hour intervall must be 1 (Otherwise it doesn\' make sense to display minutes).');
     2872        }
     2873               
     2874        // Stroke all headers. As argument we supply the offset from the
     2875        // top which depends on any previous headers
     2876       
     2877        // First find out the height of each header
     2878        $offy=$this->StrokeYears(0,true);
     2879        $offm=$this->StrokeMonths($offy,true);
     2880        $offw=$this->StrokeWeeks($offm,true);
     2881        $offd=$this->StrokeDays($offw,true);
     2882        $offh=$this->StrokeHours($offd,true);
     2883        $offmin=$this->StrokeMinutes($offh,true);
     2884
     2885
     2886        // ... then we can stroke them in the "backwards order to ensure that
     2887        // the larger scale gridlines is stroked over the smaller scale gridline
     2888        $this->StrokeMinutes($offh);
     2889        $this->StrokeHours($offd);
     2890        $this->StrokeDays($offw);
     2891        $this->StrokeWeeks($offm);             
     2892        $this->StrokeMonths($offy);             
     2893        $this->StrokeYears(0);
     2894
     2895        // Now when we now the oaverall size of the scale headers
     2896        // we can stroke the overall table headers
     2897        $this->StrokeTableHeaders($offmin);
     2898               
     2899        // Now we can calculate the correct scaling factor for each vertical position
     2900        $this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd;               
     2901        $this->iVertHeaderSize = $offmin;
     2902        if( $this->iVertSpacing == -1 )
     2903            $this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines;
     2904    }   
    30142905}
    30152906
     
    30262917    public $iConstrainArrowType;
    30272918
    3028     //---------------
    3029     // CONSTRUCTOR
    3030     function __construct($aRow,$aType,$aColor,$aArrowSize,$aArrowType){
    3031         $this->iConstrainType = $aType;
    3032         $this->iConstrainRow = $aRow;
    3033         $this->iConstrainColor=$aColor;
    3034         $this->iConstrainArrowSize=$aArrowSize;
    3035         $this->iConstrainArrowType=$aArrowType;
     2919//---------------
     2920// CONSTRUCTOR
     2921    function GanttConstraint($aRow,$aType,$aColor,$aArrowSize,$aArrowType){
     2922        $this->iConstrainType = $aType;
     2923        $this->iConstrainRow = $aRow;
     2924        $this->iConstrainColor=$aColor;
     2925        $this->iConstrainArrowSize=$aArrowSize;
     2926        $this->iConstrainArrowType=$aArrowType;
    30362927    }
    30372928}
     
    30452936    public $title,$caption;
    30462937    public $csimarea='',$csimtarget='',$csimwintarget='',$csimalt='';
    3047     public $constraints = array();
     2938    public $constraints = array();   
    30482939    public $iCaptionMargin=5;
    30492940    public $iConstrainPos=array();
    3050     protected $iStart="";    // Start date
    3051     public $iVPos=0;     // Vertical position
    3052     protected $iLabelLeftMargin=2; // Title margin
    3053 
    3054     function __construct() {
    3055         $this->title = new TextProperty();
    3056         $this->title->Align('left','center');
    3057         $this->caption = new TextProperty();
     2941    protected $iStart="";                               // Start date
     2942    public $iVPos=0;                                    // Vertical position
     2943    protected $iLabelLeftMargin=2;      // Title margin
     2944               
     2945    function GanttPlotObject() {
     2946        $this->title = new TextProperty();
     2947        $this->title->Align("left","center");
     2948        $this->caption = new TextProperty();
    30582949    }
    30592950
    30602951    function GetCSIMArea() {
    3061         return $this->csimarea;
     2952        return $this->csimarea;
    30622953    }
    30632954
    30642955    function SetCSIMTarget($aTarget,$aAlt='',$aWinTarget='') {
    3065         if( !is_string($aTarget) ) {
    3066             $tv = substr(var_export($aTarget,true),0,40);
    3067             JpGraphError::RaiseL(6024,$tv);
    3068             //('CSIM Target must be specified as a string.'."\nStart of target is:\n$tv");
    3069         }
    3070         if( !is_string($aAlt) ) {
    3071             $tv = substr(var_export($aAlt,true),0,40);
    3072             JpGraphError::RaiseL(6025,$tv);
    3073             //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv");
    3074         }
     2956        if( !is_string($aTarget) ) {
     2957            $tv = substr(var_export($aTarget,true),0,40);
     2958            JpGraphError::RaiseL(6024,$tv);
     2959//('CSIM Target must be specified as a string.'."\nStart of target is:\n$tv");
     2960        }
     2961        if( !is_string($aAlt) ) {
     2962            $tv = substr(var_export($aAlt,true),0,40);
     2963            JpGraphError::RaiseL(6025,$tv);
     2964//('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv");
     2965        }
    30752966
    30762967        $this->csimtarget=$aTarget;
     
    30782969        $this->csimalt=$aAlt;
    30792970    }
    3080 
     2971   
    30812972    function SetCSIMAlt($aAlt) {
    3082         if( !is_string($aAlt) ) {
    3083             $tv = substr(var_export($aAlt,true),0,40);
    3084             JpGraphError::RaiseL(6025,$tv);
    3085             //('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv");
    3086         }
     2973        if( !is_string($aAlt) ) {
     2974            $tv = substr(var_export($aAlt,true),0,40);
     2975            JpGraphError::RaiseL(6025,$tv);
     2976//('CSIM Alt text must be specified as a string.'."\nStart of alt text is:\n$tv");
     2977        }
    30872978        $this->csimalt=$aAlt;
    30882979    }
    30892980
    30902981    function SetConstrain($aRow,$aType,$aColor='black',$aArrowSize=ARROW_S2,$aArrowType=ARROWT_SOLID) {
    3091         $this->constraints[] = new GanttConstraint($aRow, $aType, $aColor, $aArrowSize, $aArrowType);
     2982        $this->constraints[] = new GanttConstraint($aRow, $aType, $aColor, $aArrowSize, $aArrowType);
    30922983    }
    30932984
    30942985    function SetConstrainPos($xt,$yt,$xb,$yb) {
    3095         $this->iConstrainPos = array($xt,$yt,$xb,$yb);
    3096     }
    3097 
     2986        $this->iConstrainPos = array($xt,$yt,$xb,$yb);
     2987    }
     2988
     2989    /*
     2990    function GetConstrain() {
     2991        return array($this->iConstrainRow,$this->iConstrainType);
     2992    }
     2993    */
     2994       
    30982995    function GetMinDate() {
    3099         return $this->iStart;
     2996        return $this->iStart;
    31002997    }
    31012998
    31022999    function GetMaxDate() {
    3103         return $this->iStart;
    3104     }
    3105 
     3000        return $this->iStart;
     3001    }
     3002       
    31063003    function SetCaptionMargin($aMarg) {
    3107         $this->iCaptionMargin=$aMarg;
     3004        $this->iCaptionMargin=$aMarg;
    31083005    }
    31093006
    31103007    function GetAbsHeight($aImg) {
    3111         return 0;
    3112     }
    3113 
     3008        return 0;
     3009    }
     3010       
    31143011    function GetLineNbr() {
    3115         return $this->iVPos;
     3012        return $this->iVPos;
    31163013    }
    31173014
    31183015    function SetLabelLeftMargin($aOff) {
    3119         $this->iLabelLeftMargin=$aOff;
    3120     }
     3016        $this->iLabelLeftMargin=$aOff;
     3017    }           
    31213018
    31223019    function StrokeActInfo($aImg,$aScale,$aYPos) {
    3123         $cols=array();
    3124         $aScale->actinfo->GetColStart($aImg,$cols,true);
    3125         $this->title->Stroke($aImg,$cols,$aYPos);
     3020        $cols=array();
     3021        $aScale->actinfo->GetColStart($aImg,$cols,true);
     3022        $this->title->Stroke($aImg,$cols,$aYPos);               
    31263023    }
    31273024}
     
    31293026//===================================================
    31303027// CLASS Progress
    3131 // Holds parameters for the progress indicator
     3028// Holds parameters for the progress indicator 
    31323029// displyed within a bar
    31333030//===================================================
     
    31363033    public $iPattern=GANTT_SOLID;
    31373034    public $iColor="black", $iFillColor='black';
    3138     public $iDensity=98, $iHeight=0.65;
    3139 
     3035    public $iDensity=98, $iHeight=0.65; 
     3036       
    31403037    function Set($aProg) {
    3141         if( $aProg < 0.0 || $aProg > 1.0 ) {
    3142                 JpGraphError::RaiseL(6027);
    3143                 //("Progress value must in range [0, 1]");
    3144         }
    3145         $this->iProgress = $aProg;
    3146     }
    3147 
    3148     function SetPattern($aPattern,$aColor="blue",$aDensity=98) {
    3149         $this->iPattern = $aPattern;
    3150         $this->iColor = $aColor;
    3151         $this->iDensity = $aDensity;
     3038        if( $aProg < 0.0 || $aProg > 1.0 )
     3039            JpGraphError::RaiseL(6027);
     3040//("Progress value must in range [0, 1]");
     3041        $this->iProgress = $aProg;
     3042    }
     3043
     3044    function SetPattern($aPattern,$aColor="blue",$aDensity=98) {               
     3045        $this->iPattern = $aPattern;
     3046        $this->iColor = $aColor;
     3047        $this->iDensity = $aDensity;
    31523048    }
    31533049
    31543050    function SetFillColor($aColor) {
    3155         $this->iFillColor = $aColor;
    3156     }
    3157 
     3051        $this->iFillColor = $aColor;
     3052    }
     3053       
    31583054    function SetHeight($aHeight) {
    3159         $this->iHeight = $aHeight;
     3055        $this->iHeight = $aHeight;
    31603056    }
    31613057}
     
    31753071    private $iStart=0; // 0=from left margin, 1=just along header
    31763072
    3177     function __construct() {
    3178         $this->line = new LineProperty();
    3179         $this->line->SetColor('gray@0.4');
    3180         $this->line->SetStyle('dashed');
    3181     }
    3182 
     3073    function HorizontalGridLine() {
     3074        $this->line = new LineProperty();
     3075        $this->line->SetColor('gray@0.4');
     3076        $this->line->SetStyle('dashed');
     3077    }
     3078   
    31833079    function Show($aShow=true) {
    3184         $this->iShow = $aShow;
     3080        $this->iShow = $aShow;
    31853081    }
    31863082
    31873083    function SetRowFillColor($aColor1,$aColor2='') {
    3188         $this->iRowColor1 = $aColor1;
    3189         $this->iRowColor2 = $aColor2;
     3084        $this->iRowColor1 = $aColor1;
     3085        $this->iRowColor2 = $aColor2;
    31903086    }
    31913087
    31923088    function SetStart($aStart) {
    3193         $this->iStart = $aStart;
     3089        $this->iStart = $aStart;
    31943090    }
    31953091
    31963092    function Stroke($aImg,$aScale) {
    3197 
    3198         if( ! $this->iShow ) return;
    3199 
    3200         // Get horizontal width of line
    3201         /*
    3202         $limst = $aScale->iStartDate;
    3203         $limen = $aScale->iEndDate;
    3204         $xt = round($aScale->TranslateDate($aScale->iStartDate));
    3205         $xb = round($aScale->TranslateDate($limen));
    3206         */
    3207 
    3208         if( $this->iStart === 0 ) {
    3209             $xt = $aImg->left_margin-1;
    3210         }
    3211         else {
    3212             $xt = round($aScale->TranslateDate($aScale->iStartDate))+1;
    3213         }
    3214 
    3215         $xb = $aImg->width-$aImg->right_margin;
    3216 
    3217         $yt = round($aScale->TranslateVertPos(0));
    3218         $yb = round($aScale->TranslateVertPos(1));
    3219         $height = $yb - $yt;
    3220 
    3221         // Loop around for all lines in the chart
    3222         for($i=0; $i < $aScale->iVertLines; ++$i ) {
    3223             $yb = $yt - $height;
    3224             $this->line->Stroke($aImg,$xt,$yb,$xb,$yb);
    3225             if( $this->iRowColor1 !== '' ) {
    3226                 if( $i % 2 == 0 ) {
    3227                     $aImg->PushColor($this->iRowColor1);
    3228                     $aImg->FilledRectangle($xt,$yt,$xb,$yb);
    3229                     $aImg->PopColor();
    3230                 }
    3231                 elseif( $this->iRowColor2 !== '' ) {
    3232                     $aImg->PushColor($this->iRowColor2);
    3233                     $aImg->FilledRectangle($xt,$yt,$xb,$yb);
    3234                     $aImg->PopColor();
    3235                 }
    3236             }
    3237             $yt = round($aScale->TranslateVertPos($i+1));
    3238         }
    3239         $yb = $yt - $height;
    3240         $this->line->Stroke($aImg,$xt,$yb,$xb,$yb);
     3093       
     3094        if( ! $this->iShow ) return;
     3095
     3096        // Get horizontal width of line
     3097        /*
     3098        $limst = $aScale->iStartDate;
     3099        $limen = $aScale->iEndDate;
     3100        $xt = round($aScale->TranslateDate($aScale->iStartDate));
     3101        $xb = round($aScale->TranslateDate($limen));
     3102        */
     3103
     3104        if( $this->iStart === 0 ) {
     3105            $xt = $aImg->left_margin-1;
     3106        }
     3107        else {
     3108            $xt = round($aScale->TranslateDate($aScale->iStartDate))+1;
     3109        }
     3110
     3111        $xb = $aImg->width-$aImg->right_margin;
     3112
     3113        $yt = round($aScale->TranslateVertPos(0));
     3114        $yb = round($aScale->TranslateVertPos(1));         
     3115        $height = $yb - $yt;
     3116
     3117        // Loop around for all lines in the chart
     3118        for($i=0; $i < $aScale->iVertLines; ++$i ) {
     3119            $yb = $yt - $height;
     3120            $this->line->Stroke($aImg,$xt,$yb,$xb,$yb);
     3121            if( $this->iRowColor1 !== '' ) {
     3122                if( $i % 2 == 0 ) {
     3123                    $aImg->PushColor($this->iRowColor1);
     3124                    $aImg->FilledRectangle($xt,$yt,$xb,$yb);
     3125                    $aImg->PopColor();
     3126                }
     3127                elseif( $this->iRowColor2 !== '' ) {
     3128                    $aImg->PushColor($this->iRowColor2);
     3129                    $aImg->FilledRectangle($xt,$yt,$xb,$yb);
     3130                    $aImg->PopColor();
     3131                }
     3132            }
     3133            $yt = round($aScale->TranslateVertPos($i+1));
     3134        }
     3135        $yb = $yt - $height;
     3136        $this->line->Stroke($aImg,$xt,$yb,$xb,$yb);
    32413137    }
    32423138}
     
    32553151    private $iShadow=false,$iShadowColor="darkgray",$iShadowWidth=1,$iShadowFrame="black";
    32563152    private $iPattern=GANTT_RDIAG,$iPatternColor="blue",$iPatternDensity=95;
    3257     private $iBreakStyle=false, $iBreakLineStyle='dotted',$iBreakLineWeight=1;
    3258     //---------------
    3259     // CONSTRUCTOR
    3260     function __construct($aPos,$aLabel,$aStart,$aEnd,$aCaption="",$aHeightFactor=0.6) {
    3261         parent::__construct();
    3262         $this->iStart = $aStart;
    3263         // Is the end date given as a date or as number of days added to start date?
    3264         if( is_string($aEnd) ) {
    3265             // If end date has been specified without a time we will asssume
    3266             // end date is at the end of that date
    3267             if( strpos($aEnd,':') === false ) {
    3268                 $this->iEnd = strtotime($aEnd)+SECPERDAY-1;
    3269             }
    3270             else {
    3271                 $this->iEnd = $aEnd;
    3272             }
    3273         }
    3274         elseif(is_int($aEnd) || is_float($aEnd) ) {
    3275                 $this->iEnd = strtotime($aStart)+round($aEnd*SECPERDAY);
    3276         }
    3277         $this->iVPos = $aPos;
    3278         $this->iHeightFactor = $aHeightFactor;
    3279         $this->title->Set($aLabel);
    3280         $this->caption = new TextProperty($aCaption);
    3281         $this->caption->Align("left","center");
    3282         $this->leftMark =new PlotMark();
    3283         $this->leftMark->Hide();
    3284         $this->rightMark=new PlotMark();
    3285         $this->rightMark->Hide();
    3286         $this->progress = new Progress();
    3287     }
    3288 
    3289     //---------------
    3290     // PUBLIC METHODS
     3153//---------------
     3154// CONSTRUCTOR 
     3155    function GanttBar($aPos,$aLabel,$aStart,$aEnd,$aCaption="",$aHeightFactor=0.6) {
     3156        parent::GanttPlotObject();     
     3157        $this->iStart = $aStart;       
     3158        // Is the end date given as a date or as number of days added to start date?
     3159        if( is_string($aEnd) ) {
     3160            // If end date has been specified without a time we will asssume
     3161            // end date is at the end of that date
     3162            if( strpos($aEnd,':') === false )
     3163                $this->iEnd = strtotime($aEnd)+SECPERDAY-1;
     3164            else
     3165                $this->iEnd = $aEnd;
     3166        }
     3167        elseif(is_int($aEnd) || is_float($aEnd) )
     3168            $this->iEnd = strtotime($aStart)+round($aEnd*SECPERDAY);
     3169        $this->iVPos = $aPos;
     3170        $this->iHeightFactor = $aHeightFactor;
     3171        $this->title->Set($aLabel);
     3172        $this->caption = new TextProperty($aCaption);
     3173        $this->caption->Align("left","center");
     3174        $this->leftMark =new PlotMark();
     3175        $this->leftMark->Hide();
     3176        $this->rightMark=new PlotMark();
     3177        $this->rightMark->Hide();
     3178        $this->progress = new Progress();
     3179    }
     3180       
     3181//---------------
     3182// PUBLIC METHODS       
    32913183    function SetShadow($aShadow=true,$aColor="gray") {
    3292         $this->iShadow=$aShadow;
    3293         $this->iShadowColor=$aColor;
    3294     }
    3295 
    3296     function SetBreakStyle($aFlg=true,$aLineStyle='dotted',$aLineWeight=1) {
    3297         $this->iBreakStyle = $aFlg;
    3298         $this->iBreakLineStyle = $aLineStyle;
    3299         $this->iBreakLineWeight = $aLineWeight;
    3300     }
    3301 
     3184        $this->iShadow=$aShadow;
     3185        $this->iShadowColor=$aColor;
     3186    }
     3187   
    33023188    function GetMaxDate() {
    3303         return $this->iEnd;
    3304     }
    3305 
     3189        return $this->iEnd;
     3190    }
     3191       
    33063192    function SetHeight($aHeight) {
    3307         $this->iHeightFactor = $aHeight;
     3193        $this->iHeightFactor = $aHeight;
    33083194    }
    33093195
    33103196    function SetColor($aColor) {
    3311         $this->iFrameColor = $aColor;
     3197        $this->iFrameColor = $aColor;
    33123198    }
    33133199
    33143200    function SetFillColor($aColor) {
    3315         $this->iFillColor = $aColor;
     3201        $this->iFillColor = $aColor;
    33163202    }
    33173203
    33183204    function GetAbsHeight($aImg) {
    3319         if( is_int($this->iHeightFactor) || $this->leftMark->show || $this->rightMark->show ) {
    3320             $m=-1;
    3321             if( is_int($this->iHeightFactor) )
    3322                 $m = $this->iHeightFactor;
    3323             if( $this->leftMark->show )
    3324                 $m = max($m,$this->leftMark->width*2);
    3325             if( $this->rightMark->show )
    3326                 $m = max($m,$this->rightMark->width*2);
    3327             return $m;
    3328         }
    3329         else
    3330                 return -1;
    3331     }
    3332 
    3333     function SetPattern($aPattern,$aColor="blue",$aDensity=95) {
    3334         $this->iPattern = $aPattern;
    3335         $this->iPatternColor = $aColor;
    3336         $this->iPatternDensity = $aDensity;
     3205        if( is_int($this->iHeightFactor) || $this->leftMark->show || $this->rightMark->show ) {
     3206            $m=-1;
     3207            if( is_int($this->iHeightFactor) )
     3208                $m = $this->iHeightFactor;
     3209            if( $this->leftMark->show )
     3210                $m = max($m,$this->leftMark->width*2);
     3211            if( $this->rightMark->show )
     3212                $m = max($m,$this->rightMark->width*2);
     3213            return $m;
     3214        }
     3215        else
     3216            return -1;
     3217    }
     3218       
     3219    function SetPattern($aPattern,$aColor="blue",$aDensity=95) {               
     3220        $this->iPattern = $aPattern;
     3221        $this->iPatternColor = $aColor;
     3222        $this->iPatternDensity = $aDensity;
    33373223    }
    33383224
    33393225    function Stroke($aImg,$aScale) {
    3340         $factory = new RectPatternFactory();
    3341         $prect = $factory->Create($this->iPattern,$this->iPatternColor);
    3342         $prect->SetDensity($this->iPatternDensity);
    3343 
    3344         // If height factor is specified as a float between 0,1 then we take it as meaning
    3345         // percetage of the scale width between horizontal line.
    3346         // If it is an integer > 1 we take it to mean the absolute height in pixels
    3347         if( $this->iHeightFactor > -0.0 && $this->iHeightFactor <= 1.1)
    3348                 $vs = $aScale->GetVertSpacing()*$this->iHeightFactor;
    3349         elseif(is_int($this->iHeightFactor) && $this->iHeightFactor>2 && $this->iHeightFactor < 200 )
    3350                 $vs = $this->iHeightFactor;
    3351         else {
    3352                 JpGraphError::RaiseL(6028,$this->iHeightFactor);
    3353                 //      ("Specified height (".$this->iHeightFactor.") for gantt bar is out of range.");
    3354         }
    3355 
    3356         // Clip date to min max dates to show
    3357         $st = $aScale->NormalizeDate($this->iStart);
    3358         $en = $aScale->NormalizeDate($this->iEnd);
    3359 
    3360         $limst = max($st,$aScale->iStartDate);
    3361         $limen = min($en,$aScale->iEndDate);
    3362 
    3363         $xt = round($aScale->TranslateDate($limst));
    3364         $xb = round($aScale->TranslateDate($limen));
    3365         $yt = round($aScale->TranslateVertPos($this->iVPos)-$vs-($aScale->GetVertSpacing()/2-$vs/2));
    3366         $yb = round($aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2-$vs/2));
    3367         $middle = round($yt+($yb-$yt)/2);
    3368         $this->StrokeActInfo($aImg,$aScale,$middle);
    3369 
    3370         // CSIM for title
    3371         if( ! empty($this->title->csimtarget) ) {
    3372             $colwidth = $this->title->GetColWidth($aImg);
    3373             $colstarts=array();
    3374             $aScale->actinfo->GetColStart($aImg,$colstarts,true);
    3375             $n = min(count($colwidth),count($this->title->csimtarget));
    3376             for( $i=0; $i < $n; ++$i ) {
    3377                 $title_xt = $colstarts[$i];
    3378                 $title_xb = $title_xt + $colwidth[$i];
    3379                 $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb";
    3380 
    3381                 if( ! empty($this->title->csimtarget[$i]) ) {
    3382                     $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\"";
    3383 
    3384                     if( ! empty($this->title->csimwintarget[$i]) ) {
    3385                         $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\" ";
    3386                     }
    3387 
    3388                     if( ! empty($this->title->csimalt[$i]) ) {
    3389                         $tmp = $this->title->csimalt[$i];
    3390                         $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" ";
    3391                     }
    3392                     $this->csimarea .= " />\n";
    3393                 }
    3394             }
    3395         }
    3396 
    3397         // Check if the bar is totally outside the current scale range
    3398         if( $en <  $aScale->iStartDate || $st > $aScale->iEndDate )
    3399                 return;
    3400 
    3401 
    3402         // Remember the positions for the bar
    3403         $this->SetConstrainPos($xt,$yt,$xb,$yb);
    3404 
    3405 
    3406 
    3407         $prect->ShowFrame(false);
    3408         $prect->SetBackground($this->iFillColor);
    3409         if( $this->iBreakStyle ) {
    3410                 $aImg->SetColor($this->iFrameColor);
    3411                 $olds = $aImg->SetLineStyle($this->iBreakLineStyle);
    3412                 $oldw = $aImg->SetLineWeight($this->iBreakLineWeight);
    3413                 $aImg->StyleLine($xt,$yt,$xb,$yt);
    3414                 $aImg->StyleLine($xt,$yb,$xb,$yb);
    3415                 $aImg->SetLineStyle($olds);
    3416                 $aImg->SetLineWeight($oldw);
    3417         }
    3418         else {
    3419                 if( $this->iShadow ) {
    3420                     $aImg->SetColor($this->iFrameColor);
    3421                     $aImg->ShadowRectangle($xt,$yt,$xb,$yb,$this->iFillColor,$this->iShadowWidth,$this->iShadowColor);
    3422                     $prect->SetPos(new Rectangle($xt+1,$yt+1,$xb-$xt-$this->iShadowWidth-2,$yb-$yt-$this->iShadowWidth-2));
    3423                     $prect->Stroke($aImg);
    3424                 }
    3425                 else {
    3426                     $prect->SetPos(new Rectangle($xt,$yt,$xb-$xt+1,$yb-$yt+1));
    3427                     $prect->Stroke($aImg);
    3428                     $aImg->SetColor($this->iFrameColor);
    3429                     $aImg->Rectangle($xt,$yt,$xb,$yb);
    3430                 }
    3431         }
    3432         // CSIM for bar
    3433         if( ! empty($this->csimtarget) ) {
    3434 
    3435             $coords = "$xt,$yt,$xb,$yt,$xb,$yb,$xt,$yb";
    3436             $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtarget."\"";
    3437 
    3438             if( !empty($this->csimwintarget) ) {
    3439                 $this->csimarea .= " target=\"".$this->csimwintarget."\" ";
    3440             }
    3441 
    3442             if( $this->csimalt != '' ) {
    3443                 $tmp = $this->csimalt;
    3444                 $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" ";
    3445             }
    3446             $this->csimarea .= " />\n";
    3447         }
    3448 
    3449         // Draw progress bar inside activity bar
    3450         if( $this->progress->iProgress > 0 ) {
    3451 
    3452             $xtp = $aScale->TranslateDate($st);
    3453             $xbp = $aScale->TranslateDate($en);
    3454             $len = ($xbp-$xtp)*$this->progress->iProgress;
    3455 
    3456             $endpos = $xtp+$len;
    3457             if( $endpos > $xt ) {
    3458 
    3459                 // Take away the length of the progress that is not visible (before the start date)
    3460                 $len -= ($xt-$xtp);
    3461 
    3462                 // Is the the progress bar visible after the start date?
    3463                 if( $xtp < $xt )
    3464                 $xtp = $xt;
    3465 
    3466                 // Make sure that the progess bar doesn't extend over the end date
    3467                 if( $xtp+$len-1 > $xb )
    3468                 $len = $xb - $xtp ;
    3469 
    3470                 $prog = $factory->Create($this->progress->iPattern,$this->progress->iColor);
    3471                 $prog->SetDensity($this->progress->iDensity);
    3472                 $prog->SetBackground($this->progress->iFillColor);
    3473                 $barheight = ($yb-$yt+1);
    3474                 if( $this->iShadow )
    3475                         $barheight -= $this->iShadowWidth;
    3476                 $progressheight = floor($barheight*$this->progress->iHeight);
    3477                 $marg = ceil(($barheight-$progressheight)/2);
    3478                 $pos = new Rectangle($xtp,$yt + $marg, $len,$barheight-2*$marg);
    3479                 $prog->SetPos($pos);
    3480                 $prog->Stroke($aImg);
    3481             }
    3482         }
    3483 
    3484         // We don't plot the end mark if the bar has been capped
    3485         if( $limst == $st ) {
    3486             $y = $middle;
    3487             // We treat the RIGHT and LEFT triangle mark a little bi
    3488             // special so that these marks are placed right under the
    3489             // bar.
    3490             if( $this->leftMark->GetType() == MARK_LEFTTRIANGLE ) {
    3491                 $y = $yb ;
    3492             }
    3493             $this->leftMark->Stroke($aImg,$xt,$y);
    3494         }
    3495         if( $limen == $en ) {
    3496             $y = $middle;
    3497             // We treat the RIGHT and LEFT triangle mark a little bi
    3498             // special so that these marks are placed right under the
    3499             // bar.
    3500             if( $this->rightMark->GetType() == MARK_RIGHTTRIANGLE ) {
    3501                 $y = $yb ;
    3502             }
    3503             $this->rightMark->Stroke($aImg,$xb,$y);
    3504 
    3505             $margin = $this->iCaptionMargin;
    3506             if( $this->rightMark->show )
    3507                 $margin += $this->rightMark->GetWidth();
    3508             $this->caption->Stroke($aImg,$xb+$margin,$middle);
    3509         }
     3226        $factory = new RectPatternFactory();
     3227        $prect = $factory->Create($this->iPattern,$this->iPatternColor);
     3228        $prect->SetDensity($this->iPatternDensity);
     3229
     3230        // If height factor is specified as a float between 0,1 then we take it as meaning
     3231        // percetage of the scale width between horizontal line.
     3232        // If it is an integer > 1 we take it to mean the absolute height in pixels
     3233        if( $this->iHeightFactor > -0.0 && $this->iHeightFactor <= 1.1)
     3234            $vs = $aScale->GetVertSpacing()*$this->iHeightFactor;
     3235        elseif(is_int($this->iHeightFactor) && $this->iHeightFactor>2 && $this->iHeightFactor < 200 )
     3236            $vs = $this->iHeightFactor;
     3237        else
     3238            JpGraphError::RaiseL(6028,$this->iHeightFactor);
     3239//("Specified height (".$this->iHeightFactor.") for gantt bar is out of range.");
     3240       
     3241        // Clip date to min max dates to show
     3242        $st = $aScale->NormalizeDate($this->iStart);
     3243        $en = $aScale->NormalizeDate($this->iEnd);
     3244       
     3245
     3246        $limst = max($st,$aScale->iStartDate);
     3247        $limen = min($en,$aScale->iEndDate);
     3248                       
     3249        $xt = round($aScale->TranslateDate($limst));
     3250        $xb = round($aScale->TranslateDate($limen));
     3251        $yt = round($aScale->TranslateVertPos($this->iVPos)-$vs-($aScale->GetVertSpacing()/2-$vs/2));
     3252        $yb = round($aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2-$vs/2));
     3253        $middle = round($yt+($yb-$yt)/2);
     3254        $this->StrokeActInfo($aImg,$aScale,$middle);
     3255
     3256        // CSIM for title
     3257        if( ! empty($this->title->csimtarget) ) {
     3258            $colwidth = $this->title->GetColWidth($aImg);
     3259            $colstarts=array();
     3260            $aScale->actinfo->GetColStart($aImg,$colstarts,true);
     3261            $n = min(count($colwidth),count($this->title->csimtarget));
     3262            for( $i=0; $i < $n; ++$i ) {
     3263                $title_xt = $colstarts[$i];
     3264                $title_xb = $title_xt + $colwidth[$i];
     3265                $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb";
     3266
     3267                if( ! empty($this->title->csimtarget[$i]) ) {
     3268                    $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\"";
     3269                   
     3270                    if( ! empty($this->title->csimwintarget[$i]) ) {
     3271                        $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\" ";
     3272                    }
     3273                   
     3274                    if( ! empty($this->title->csimalt[$i]) ) {
     3275                        $tmp = $this->title->csimalt[$i];
     3276                        $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" ";
     3277                    }
     3278                    $this->csimarea .= " />\n";
     3279                }
     3280            }
     3281        }
     3282       
     3283        // Check if the bar is totally outside the current scale range
     3284        if( $en <  $aScale->iStartDate || $st > $aScale->iEndDate )
     3285                return;
     3286                       
     3287
     3288        // Remember the positions for the bar
     3289        $this->SetConstrainPos($xt,$yt,$xb,$yb);
     3290               
     3291        $prect->ShowFrame(false);
     3292        $prect->SetBackground($this->iFillColor);
     3293        if( $this->iShadow ) {
     3294            $aImg->SetColor($this->iFrameColor);
     3295            $aImg->ShadowRectangle($xt,$yt,$xb,$yb,$this->iFillColor,$this->iShadowWidth,$this->iShadowColor);                         
     3296            $prect->SetPos(new Rectangle($xt+1,$yt+1,$xb-$xt-$this->iShadowWidth-2,$yb-$yt-$this->iShadowWidth-2));                             
     3297            $prect->Stroke($aImg);
     3298        }
     3299        else { 
     3300            $prect->SetPos(new Rectangle($xt,$yt,$xb-$xt+1,$yb-$yt+1));                         
     3301            $prect->Stroke($aImg);
     3302            $aImg->SetColor($this->iFrameColor);
     3303            $aImg->Rectangle($xt,$yt,$xb,$yb);
     3304        }
     3305
     3306        // CSIM for bar
     3307        if( ! empty($this->csimtarget) ) {
     3308
     3309            $coords = "$xt,$yt,$xb,$yt,$xb,$yb,$xt,$yb";
     3310            $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtarget."\"";
     3311           
     3312            if( !empty($this->csimwintarget) ) {
     3313                $this->csimarea .= " target=\"".$this->csimwintarget."\" ";
     3314            }
     3315
     3316            if( $this->csimalt != '' ) {
     3317                $tmp = $this->csimalt;
     3318                $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" ";
     3319            }
     3320            $this->csimarea .= " />\n";
     3321        }
     3322
     3323        // Draw progress bar inside activity bar
     3324        if( $this->progress->iProgress > 0 ) {
     3325               
     3326            $xtp = $aScale->TranslateDate($st);
     3327            $xbp = $aScale->TranslateDate($en);
     3328            $len = ($xbp-$xtp)*$this->progress->iProgress;
     3329
     3330            $endpos = $xtp+$len;
     3331            if( $endpos > $xt ) {
     3332
     3333                // Take away the length of the progress that is not visible (before the start date)
     3334                $len -= ($xt-$xtp);
     3335
     3336                // Is the the progress bar visible after the start date?
     3337                if( $xtp < $xt )
     3338                    $xtp = $xt;
     3339               
     3340                // Make sure that the progess bar doesn't extend over the end date
     3341                if( $xtp+$len-1 > $xb )
     3342                    $len = $xb - $xtp ;
     3343               
     3344                $prog = $factory->Create($this->progress->iPattern,$this->progress->iColor);
     3345                $prog->SetDensity($this->progress->iDensity);
     3346                $prog->SetBackground($this->progress->iFillColor);
     3347                $barheight = ($yb-$yt+1);
     3348                if( $this->iShadow )
     3349                    $barheight -= $this->iShadowWidth;
     3350                $progressheight = floor($barheight*$this->progress->iHeight);
     3351                $marg = ceil(($barheight-$progressheight)/2);
     3352                $pos = new Rectangle($xtp,$yt + $marg, $len,$barheight-2*$marg);
     3353                $prog->SetPos($pos);
     3354                $prog->Stroke($aImg);
     3355            }
     3356        }
     3357       
     3358        // We don't plot the end mark if the bar has been capped
     3359        if( $limst == $st ) {
     3360            $y = $middle;
     3361            // We treat the RIGHT and LEFT triangle mark a little bi
     3362            // special so that these marks are placed right under the
     3363            // bar.
     3364            if( $this->leftMark->GetType() == MARK_LEFTTRIANGLE ) {
     3365                $y = $yb ;
     3366            }
     3367            $this->leftMark->Stroke($aImg,$xt,$y);
     3368        }
     3369        if( $limen == $en ) {
     3370            $y = $middle;
     3371            // We treat the RIGHT and LEFT triangle mark a little bi
     3372            // special so that these marks are placed right under the
     3373            // bar.
     3374            if( $this->rightMark->GetType() == MARK_RIGHTTRIANGLE ) {
     3375                $y = $yb ;
     3376            }
     3377            $this->rightMark->Stroke($aImg,$xb,$y);
     3378           
     3379            $margin = $this->iCaptionMargin;
     3380            if( $this->rightMark->show )
     3381                $margin += $this->rightMark->GetWidth();
     3382            $this->caption->Stroke($aImg,$xb+$margin,$middle);         
     3383        }
    35103384    }
    35113385}
     
    35173391class MileStone extends GanttPlotObject {
    35183392    public $mark;
    3519 
    3520     //---------------
    3521     // CONSTRUCTOR
    3522     function __construct($aVPos,$aLabel,$aDate,$aCaption="") {
    3523         GanttPlotObject::__construct();
    3524         $this->caption->Set($aCaption);
    3525         $this->caption->Align("left","center");
    3526         $this->caption->SetFont(FF_FONT1,FS_BOLD);
    3527         $this->title->Set($aLabel);
    3528         $this->title->SetColor("darkred");
    3529         $this->mark = new PlotMark();
    3530         $this->mark->SetWidth(10);
    3531         $this->mark->SetType(MARK_DIAMOND);
    3532         $this->mark->SetColor("darkred");
    3533         $this->mark->SetFillColor("darkred");
    3534         $this->iVPos = $aVPos;
    3535         $this->iStart = $aDate;
    3536     }
    3537 
    3538     //---------------
    3539     // PUBLIC METHODS
    3540 
     3393       
     3394//---------------
     3395// CONSTRUCTOR 
     3396    function MileStone($aVPos,$aLabel,$aDate,$aCaption="") {
     3397        GanttPlotObject::GanttPlotObject();
     3398        $this->caption->Set($aCaption);
     3399        $this->caption->Align("left","center");
     3400        $this->caption->SetFont(FF_FONT1,FS_BOLD);
     3401        $this->title->Set($aLabel);
     3402        $this->title->SetColor("darkred");
     3403        $this->mark = new PlotMark();
     3404        $this->mark->SetWidth(10);
     3405        $this->mark->SetType(MARK_DIAMOND);
     3406        $this->mark->SetColor("darkred");
     3407        $this->mark->SetFillColor("darkred");
     3408        $this->iVPos = $aVPos;
     3409        $this->iStart = $aDate;
     3410    }
     3411       
     3412//---------------
     3413// PUBLIC METHODS       
     3414       
    35413415    function GetAbsHeight($aImg) {
    3542         return max($this->title->GetHeight($aImg),$this->mark->GetWidth());
    3543     }
    3544 
     3416        return max($this->title->GetHeight($aImg),$this->mark->GetWidth());
     3417    }
     3418               
    35453419    function Stroke($aImg,$aScale) {
    3546         // Put the mark in the middle at the middle of the day
    3547         $d = $aScale->NormalizeDate($this->iStart)+SECPERDAY/2;
    3548         $x = $aScale->TranslateDate($d);
    3549         $y = $aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2);
    3550 
    3551         $this->StrokeActInfo($aImg,$aScale,$y);
    3552 
    3553         // CSIM for title
    3554         if( ! empty($this->title->csimtarget) ) {
    3555 
    3556             $yt = round($y - $this->title->GetHeight($aImg)/2);
    3557             $yb = round($y + $this->title->GetHeight($aImg)/2);
    3558 
    3559             $colwidth = $this->title->GetColWidth($aImg);
    3560             $colstarts=array();
    3561             $aScale->actinfo->GetColStart($aImg,$colstarts,true);
    3562             $n = min(count($colwidth),count($this->title->csimtarget));
    3563             for( $i=0; $i < $n; ++$i ) {
    3564                 $title_xt = $colstarts[$i];
    3565                 $title_xb = $title_xt + $colwidth[$i];
    3566                 $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb";
    3567 
    3568                 if( !empty($this->title->csimtarget[$i]) ) {
    3569 
    3570                     $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\"";
    3571 
    3572                     if( !empty($this->title->csimwintarget[$i]) ) {
    3573                         $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\"";
    3574                     }
    3575 
    3576                     if( ! empty($this->title->csimalt[$i]) ) {
    3577                         $tmp = $this->title->csimalt[$i];
    3578                         $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" ";
    3579                     }
    3580                     $this->csimarea .= " />\n";
    3581                 }
    3582             }
    3583         }
    3584 
    3585         if( $d <  $aScale->iStartDate || $d > $aScale->iEndDate )
    3586                 return;
    3587 
    3588         // Remember the coordinates for any constrains linking to
    3589         // this milestone
    3590         $w = $this->mark->GetWidth()/2;
    3591         $this->SetConstrainPos($x,round($y-$w),$x,round($y+$w));
    3592 
    3593         // Setup CSIM
    3594         if( $this->csimtarget != '' ) {
    3595             $this->mark->SetCSIMTarget( $this->csimtarget );
    3596             $this->mark->SetCSIMAlt( $this->csimalt );
    3597         }
    3598 
    3599         $this->mark->Stroke($aImg,$x,$y);
    3600         $this->caption->Stroke($aImg,$x+$this->mark->width/2+$this->iCaptionMargin,$y);
    3601 
    3602         $this->csimarea .= $this->mark->GetCSIMAreas();
     3420        // Put the mark in the middle at the middle of the day
     3421        $d = $aScale->NormalizeDate($this->iStart)+SECPERDAY/2;
     3422        $x = $aScale->TranslateDate($d);
     3423        $y = $aScale->TranslateVertPos($this->iVPos)-($aScale->GetVertSpacing()/2);
     3424
     3425        $this->StrokeActInfo($aImg,$aScale,$y);
     3426
     3427        // CSIM for title
     3428        if( ! empty($this->title->csimtarget) ) {
     3429           
     3430            $yt = round($y - $this->title->GetHeight($aImg)/2);
     3431            $yb = round($y + $this->title->GetHeight($aImg)/2);
     3432
     3433            $colwidth = $this->title->GetColWidth($aImg);
     3434            $colstarts=array();
     3435            $aScale->actinfo->GetColStart($aImg,$colstarts,true);
     3436            $n = min(count($colwidth),count($this->title->csimtarget));
     3437            for( $i=0; $i < $n; ++$i ) {
     3438                $title_xt = $colstarts[$i];
     3439                $title_xb = $title_xt + $colwidth[$i];
     3440                $coords = "$title_xt,$yt,$title_xb,$yt,$title_xb,$yb,$title_xt,$yb";
     3441               
     3442                if( !empty($this->title->csimtarget[$i]) ) {
     3443                   
     3444                    $this->csimarea .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->title->csimtarget[$i]."\"";
     3445                   
     3446                    if( !empty($this->title->csimwintarget[$i]) ) {
     3447                        $this->csimarea .= "target=\"".$this->title->csimwintarget[$i]."\"";
     3448                    }
     3449                   
     3450                    if( ! empty($this->title->csimalt[$i]) ) {
     3451                        $tmp = $this->title->csimalt[$i];
     3452                        $this->csimarea .= " title=\"$tmp\" alt=\"$tmp\" ";
     3453                    }
     3454                    $this->csimarea .= " />\n";
     3455                }
     3456            }
     3457        }
     3458
     3459        if( $d <  $aScale->iStartDate || $d > $aScale->iEndDate )
     3460                return;
     3461
     3462        // Remember the coordinates for any constrains linking to
     3463        // this milestone
     3464        $w = $this->mark->GetWidth()/2;
     3465        $this->SetConstrainPos($x,round($y-$w),$x,round($y+$w));
     3466       
     3467        // Setup CSIM
     3468        if( $this->csimtarget != '' ) {
     3469            $this->mark->SetCSIMTarget( $this->csimtarget );
     3470            $this->mark->SetCSIMAlt( $this->csimalt );
     3471        }
     3472               
     3473        $this->mark->Stroke($aImg,$x,$y);               
     3474        $this->caption->Stroke($aImg,$x+$this->mark->width/2+$this->iCaptionMargin,$y);
     3475
     3476        $this->csimarea .= $this->mark->GetCSIMAreas();
    36033477    }
    36043478}
     
    36113485
    36123486class TextPropertyBelow extends TextProperty {
    3613     function __construct($aTxt='') {
    3614         parent::__construct($aTxt);
     3487    function TextPropertyBelow($aTxt='') {
     3488        parent::TextProperty($aTxt);
    36153489    }
    36163490
    36173491    function GetColWidth($aImg,$aMargin=0) {
    3618         // Since we are not stroking the title in the columns
    3619         // but rather under the graph we want this to return 0.
    3620         return array(0);
     3492        // Since we are not stroking the title in the columns
     3493        // but rather under the graph we want this to return 0.
     3494        return array(0);
    36213495    }
    36223496}
     
    36243498class GanttVLine extends GanttPlotObject {
    36253499
    3626     private $iLine,$title_margin=3, $iDayOffset=0.5;
    3627     private $iStartRow = -1, $iEndRow = -1;
    3628 
    3629     //---------------
    3630     // CONSTRUCTOR
    3631     function __construct($aDate,$aTitle="",$aColor="darkred",$aWeight=2,$aStyle="solid") {
    3632         GanttPlotObject::__construct();
    3633         $this->iLine = new LineProperty();
    3634         $this->iLine->SetColor($aColor);
    3635         $this->iLine->SetWeight($aWeight);
    3636         $this->iLine->SetStyle($aStyle);
    3637         $this->iStart = $aDate;
    3638         $this->title = new TextPropertyBelow();
    3639         $this->title->Set($aTitle);
    3640     }
    3641 
    3642     //---------------
    3643     // PUBLIC METHODS
    3644 
    3645     // Set start and end rows for the VLine. By default the entire heigh of the
    3646     // Gantt chart is used
    3647     function SetRowSpan($aStart, $aEnd=-1) {
    3648         $this->iStartRow = $aStart;
    3649         $this->iEndRow = $aEnd;
    3650     }
     3500    private $iLine,$title_margin=3, $iDayOffset=1;
     3501       
     3502//---------------
     3503// CONSTRUCTOR 
     3504    function GanttVLine($aDate,$aTitle="",$aColor="black",$aWeight=3,$aStyle="dashed") {
     3505        GanttPlotObject::GanttPlotObject();
     3506        $this->iLine = new LineProperty();
     3507        $this->iLine->SetColor($aColor);
     3508        $this->iLine->SetWeight($aWeight);
     3509        $this->iLine->SetStyle($aStyle);
     3510        $this->iStart = $aDate;
     3511        $this->title = new TextPropertyBelow();
     3512        $this->title->Set($aTitle);
     3513    }
     3514
     3515//---------------
     3516// PUBLIC METHODS       
    36513517
    36523518    function SetDayOffset($aOff=0.5) {
    3653         if( $aOff < 0.0 || $aOff > 1.0 ) {
    3654                 JpGraphError::RaiseL(6029);
    3655                 //("Offset for vertical line must be in range [0,1]");
    3656         }
    3657         $this->iDayOffset = $aOff;
    3658     }
    3659 
     3519        if( $aOff < 0.0 || $aOff > 1.0 )
     3520            JpGraphError::RaiseL(6029);
     3521//("Offset for vertical line must be in range [0,1]");
     3522        $this->iDayOffset = $aOff;
     3523    }
     3524       
    36603525    function SetTitleMargin($aMarg) {
    3661         $this->title_margin = $aMarg;
    3662     }
    3663 
    3664     function SetWeight($aWeight) {
    3665         $this->iLine->SetWeight($aWeight);
    3666     }
    3667 
     3526        $this->title_margin = $aMarg;
     3527    }
     3528       
    36683529    function Stroke($aImg,$aScale) {
    3669         $d = $aScale->NormalizeDate($this->iStart);
    3670         if( $d <  $aScale->iStartDate || $d > $aScale->iEndDate )
    3671             return;
    3672         if($this->iDayOffset != 0.0)
    3673             $d += 24*60*60*$this->iDayOffset;
    3674         $x = $aScale->TranslateDate($d);//d=1006858800,
    3675 
    3676         if( $this->iStartRow > -1 ) {
    3677             $y1 = $aScale->TranslateVertPos($this->iStartRow,true) ;
    3678         }
    3679         else {
    3680             $y1 = $aScale->iVertHeaderSize+$aImg->top_margin;
    3681         }
    3682 
    3683         if( $this->iEndRow > -1 ) {
    3684             $y2 = $aScale->TranslateVertPos($this->iEndRow);
    3685         }
    3686         else {
    3687             $y2 = $aImg->height - $aImg->bottom_margin;
    3688         }
    3689 
    3690         $this->iLine->Stroke($aImg,$x,$y1,$x,$y2);
    3691         $this->title->Align("center","top");
    3692         $this->title->Stroke($aImg,$x,$y2+$this->title_margin);
    3693     }
     3530        $d = $aScale->NormalizeDate($this->iStart);
     3531        if( $d <  $aScale->iStartDate || $d > $aScale->iEndDate )
     3532            return;     
     3533        if($this->iDayOffset != 0.0)
     3534            $d += 24*60*60*$this->iDayOffset;   
     3535        $x = $aScale->TranslateDate($d);       
     3536        $y1 = $aScale->iVertHeaderSize+$aImg->top_margin;
     3537        $y2 = $aImg->height - $aImg->bottom_margin;     
     3538        $this->iLine->Stroke($aImg,$x,$y1,$x,$y2);
     3539        $this->title->Align("center","top");
     3540        $this->title->Stroke($aImg,$x,$y2+$this->title_margin);
     3541    }   
    36943542}
    36953543
    36963544//===================================================
    36973545// CLASS LinkArrow
    3698 // Handles the drawing of a an arrow
     3546// Handles the drawing of a an arrow 
    36993547//===================================================
    37003548class LinkArrow {
    37013549    private $ix,$iy;
    37023550    private $isizespec = array(
    3703     array(2,3),array(3,5),array(3,8),array(6,15),array(8,22));
     3551        array(2,3),array(3,5),array(3,8),array(6,15),array(8,22));
    37043552    private $iDirection=ARROW_DOWN,$iType=ARROWT_SOLID,$iSize=ARROW_S2;
    37053553    private $iColor='black';
    37063554
    3707     function __construct($x,$y,$aDirection,$aType=ARROWT_SOLID,$aSize=ARROW_S2) {
    3708         $this->iDirection = $aDirection;
    3709         $this->iType = $aType;
    3710         $this->iSize = $aSize;
    3711         $this->ix = $x;
    3712         $this->iy = $y;
    3713     }
    3714 
     3555    function LinkArrow($x,$y,$aDirection,$aType=ARROWT_SOLID,$aSize=ARROW_S2) {
     3556        $this->iDirection = $aDirection;
     3557        $this->iType = $aType;
     3558        $this->iSize = $aSize;
     3559        $this->ix = $x;
     3560        $this->iy = $y;
     3561    }
     3562   
    37153563    function SetColor($aColor) {
    3716         $this->iColor = $aColor;
     3564        $this->iColor = $aColor;
    37173565    }
    37183566
    37193567    function SetSize($aSize) {
    3720         $this->iSize = $aSize;
     3568        $this->iSize = $aSize;
    37213569    }
    37223570
    37233571    function SetType($aType) {
    3724         $this->iType = $aType;
     3572        $this->iType = $aType;
    37253573    }
    37263574
    37273575    function Stroke($aImg) {
    3728         list($dx,$dy) = $this->isizespec[$this->iSize];
    3729         $x = $this->ix;
    3730         $y = $this->iy;
    3731         switch ( $this->iDirection ) {
    3732             case ARROW_DOWN:
    3733                 $c = array($x,$y,$x-$dx,$y-$dy,$x+$dx,$y-$dy,$x,$y);
    3734                 break;
    3735             case ARROW_UP:
    3736                 $c = array($x,$y,$x-$dx,$y+$dy,$x+$dx,$y+$dy,$x,$y);
    3737                 break;
    3738             case ARROW_LEFT:
    3739                 $c = array($x,$y,$x+$dy,$y-$dx,$x+$dy,$y+$dx,$x,$y);
    3740                 break;
    3741             case ARROW_RIGHT:
    3742                 $c = array($x,$y,$x-$dy,$y-$dx,$x-$dy,$y+$dx,$x,$y);
    3743                 break;
    3744             default:
    3745                 JpGraphError::RaiseL(6030);
    3746                 //('Unknown arrow direction for link.');
    3747                 die();
    3748                 break;
    3749         }
    3750         $aImg->SetColor($this->iColor);
    3751         switch( $this->iType ) {
    3752             case ARROWT_SOLID:
    3753                 $aImg->FilledPolygon($c);
    3754                 break;
    3755             case ARROWT_OPEN:
    3756                 $aImg->Polygon($c);
    3757                 break;
    3758             default:
    3759                 JpGraphError::RaiseL(6031);
    3760                 //('Unknown arrow type for link.');
    3761                 die();
    3762                 break;
    3763         }
     3576        list($dx,$dy) = $this->isizespec[$this->iSize];
     3577        $x = $this->ix;
     3578        $y = $this->iy;
     3579        switch ( $this->iDirection ) {
     3580            case ARROW_DOWN:
     3581                $c = array($x,$y,$x-$dx,$y-$dy,$x+$dx,$y-$dy,$x,$y);
     3582                break;
     3583            case ARROW_UP:
     3584                $c = array($x,$y,$x-$dx,$y+$dy,$x+$dx,$y+$dy,$x,$y);
     3585                break;
     3586            case ARROW_LEFT:
     3587                $c = array($x,$y,$x+$dy,$y-$dx,$x+$dy,$y+$dx,$x,$y);
     3588                break;
     3589            case ARROW_RIGHT:
     3590                $c = array($x,$y,$x-$dy,$y-$dx,$x-$dy,$y+$dx,$x,$y);
     3591                break;
     3592            default:
     3593                JpGraphError::RaiseL(6030);
     3594//('Unknown arrow direction for link.');
     3595                die();
     3596                break;
     3597        }
     3598        $aImg->SetColor($this->iColor);
     3599        switch( $this->iType ) {
     3600            case ARROWT_SOLID:
     3601                $aImg->FilledPolygon($c);
     3602                break;
     3603            case ARROWT_OPEN:
     3604                $aImg->Polygon($c);
     3605                break;
     3606            default:
     3607                JpGraphError::RaiseL(6031);
     3608//('Unknown arrow type for link.');
     3609                die();
     3610                break;         
     3611        }
    37643612    }
    37653613}
     
    37763624    private $iArrowSize=ARROW_S2,$iArrowType=ARROWT_SOLID;
    37773625
    3778     function __construct($x1=0,$y1=0,$x2=0,$y2=0) {
    3779         $this->ix1 = $x1;
    3780         $this->ix2 = $x2;
    3781         $this->iy1 = $y1;
    3782         $this->iy2 = $y2;
     3626    function GanttLink($x1=0,$y1=0,$x2=0,$y2=0) {
     3627        $this->ix1 = $x1;
     3628        $this->ix2 = $x2;
     3629        $this->iy1 = $y1;
     3630        $this->iy2 = $y2;
    37833631    }
    37843632
    37853633    function SetPos($x1,$y1,$x2,$y2) {
    3786         $this->ix1 = $x1;
    3787         $this->ix2 = $x2;
    3788         $this->iy1 = $y1;
    3789         $this->iy2 = $y2;
     3634        $this->ix1 = $x1;
     3635        $this->ix2 = $x2;
     3636        $this->iy1 = $y1;
     3637        $this->iy2 = $y2;
    37903638    }
    37913639
    37923640    function SetPath($aPath) {
    3793         $this->iPathType = $aPath;
     3641        $this->iPathType = $aPath;
    37943642    }
    37953643
    37963644    function SetColor($aColor) {
    3797         $this->iColor = $aColor;
     3645        $this->iColor = $aColor;
    37983646    }
    37993647
    38003648    function SetArrow($aSize,$aType=ARROWT_SOLID) {
    3801         $this->iArrowSize = $aSize;
    3802         $this->iArrowType = $aType;
    3803     }
    3804 
     3649        $this->iArrowSize = $aSize;
     3650        $this->iArrowType = $aType;
     3651    }
     3652   
    38053653    function SetWeight($aWeight) {
    3806         $this->iWeight = $aWeight;
     3654        $this->iWeight = $aWeight;
    38073655    }
    38083656
    38093657    function Stroke($aImg) {
    3810         // The way the path for the arrow is constructed is partly based
    3811         // on some heuristics. This is not an exact science but draws the
    3812         // path in a way that, for me, makes esthetic sence. For example
    3813         // if the start and end activities are very close we make a small
    3814         // detour to endter the target horixontally. If there are more
    3815         // space between axctivities then no suh detour is made and the
    3816         // target is "hit" directly vertical. I have tried to keep this
    3817         // simple. no doubt this could become almost infinitive complex
    3818         // and have some real AI. Feel free to modify this.
    3819         // This will no-doubt be tweaked as times go by. One design aim
    3820         // is to avoid having the user choose what types of arrow
    3821         // he wants.
    3822 
    3823         // The arrow is drawn between (x1,y1) to (x2,y2)
    3824         $x1 = $this->ix1 ;
    3825         $x2 = $this->ix2 ;
    3826         $y1 = $this->iy1 ;
    3827         $y2 = $this->iy2 ;
    3828 
    3829         // Depending on if the target is below or above we have to
    3830         // handle thi different.
    3831         if( $y2 > $y1 ) {
    3832             $arrowtype = ARROW_DOWN;
    3833             $midy = round(($y2-$y1)/2+$y1);
    3834             if( $x2 > $x1 ) {
    3835                 switch ( $this->iPathType  ) {
    3836                     case 0:
    3837                         $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
    3838                         break;
    3839                     case 1:
    3840                     case 2:
    3841                     case 3:
    3842                         $c = array($x1,$y1,$x2,$y1,$x2,$y2);
    3843                         break;
    3844                     default:
    3845                         JpGraphError::RaiseL(6032,$this->iPathType);
    3846                         //('Internal error: Unknown path type (='.$this->iPathType .') specified for link.');
    3847                         exit(1);
    3848                         break;
    3849                 }
    3850             }
    3851             else {
    3852                 switch ( $this->iPathType  ) {
    3853                     case 0:
    3854                     case 1:
    3855                         $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
    3856                         break;
    3857                     case 2:
    3858                         // Always extend out horizontally a bit from the first point
    3859                         // If we draw a link back in time (end to start) and the bars
    3860                         // are very close we also change the path so it comes in from
    3861                         // the left on the activity
    3862                         $c = array($x1,$y1,$x1+$this->iPathExtend,$y1,
    3863                         $x1+$this->iPathExtend,$midy,
    3864                         $x2,$midy,$x2,$y2);
    3865                         break;
    3866                     case 3:
    3867                         if( $y2-$midy < 6 ) {
    3868                             $c = array($x1,$y1,$x1,$midy,
    3869                             $x2-$this->iPathExtend,$midy,
    3870                             $x2-$this->iPathExtend,$y2,
    3871                             $x2,$y2);
    3872                             $arrowtype = ARROW_RIGHT;
    3873                         }
    3874                         else {
    3875                             $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
    3876                         }
    3877                         break;
    3878                     default:
    3879                         JpGraphError::RaiseL(6032,$this->iPathType);
    3880                         //('Internal error: Unknown path type specified for link.');
    3881                         exit(1);
    3882                         break;
    3883                 }
    3884             }
    3885             $arrow = new LinkArrow($x2,$y2,$arrowtype);
    3886         }
    3887         else {
    3888             // Y2 < Y1
    3889             $arrowtype = ARROW_UP;
    3890             $midy = round(($y1-$y2)/2+$y2);
    3891             if( $x2 > $x1 ) {
    3892                 switch ( $this->iPathType  ) {
    3893                     case 0:
    3894                     case 1:
    3895                         $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
    3896                         break;
    3897                     case 3:
    3898                         if( $midy-$y2 < 8 ) {
    3899                             $arrowtype = ARROW_RIGHT;
    3900                             $c = array($x1,$y1,$x1,$y2,$x2,$y2);
    3901                         }
    3902                         else {
    3903                             $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
    3904                         }
    3905                         break;
    3906                     default:
    3907                         JpGraphError::RaiseL(6032,$this->iPathType);
    3908                         //('Internal error: Unknown path type specified for link.');
    3909                         break;
    3910                 }
    3911             }
    3912             else {
    3913                 switch ( $this->iPathType  ) {
    3914                     case 0:
    3915                     case 1:
    3916                         $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
    3917                         break;
    3918                     case 2:
    3919                         // Always extend out horizontally a bit from the first point
    3920                         $c = array($x1,$y1,$x1+$this->iPathExtend,$y1,
    3921                         $x1+$this->iPathExtend,$midy,
    3922                         $x2,$midy,$x2,$y2);
    3923                         break;
    3924                     case 3:
    3925                         if( $midy-$y2 < 16 ) {
    3926                             $arrowtype = ARROW_RIGHT;
    3927                             $c = array($x1,$y1,$x1,$midy,$x2-$this->iPathExtend,$midy,
    3928                             $x2-$this->iPathExtend,$y2,
    3929                             $x2,$y2);
    3930                         }
    3931                         else {
    3932                             $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
    3933                         }
    3934                         break;
    3935                     default:
    3936                         JpGraphError::RaiseL(6032,$this->iPathType);
    3937                         //('Internal error: Unknown path type specified for link.');
    3938                         break;
    3939                 }
    3940             }
    3941             $arrow = new LinkArrow($x2,$y2,$arrowtype);
    3942         }
    3943         $aImg->SetColor($this->iColor);
    3944         $aImg->SetLineWeight($this->iWeight);
    3945         $aImg->Polygon($c);
    3946         $aImg->SetLineWeight(1);
    3947         $arrow->SetColor($this->iColor);
    3948         $arrow->SetSize($this->iArrowSize);
    3949         $arrow->SetType($this->iArrowType);
    3950         $arrow->Stroke($aImg);
     3658        // The way the path for the arrow is constructed is partly based
     3659        // on some heuristics. This is not an exact science but draws the
     3660        // path in a way that, for me, makes esthetic sence. For example
     3661        // if the start and end activities are very close we make a small
     3662        // detour to endter the target horixontally. If there are more
     3663        // space between axctivities then no suh detour is made and the
     3664        // target is "hit" directly vertical. I have tried to keep this
     3665        // simple. no doubt this could become almost infinitive complex
     3666        // and have some real AI. Feel free to modify this.
     3667        // This will no-doubt be tweaked as times go by. One design aim
     3668        // is to avoid having the user choose what types of arrow
     3669        // he wants.
     3670
     3671        // The arrow is drawn between (x1,y1) to (x2,y2)
     3672        $x1 = $this->ix1 ;
     3673        $x2 = $this->ix2 ;
     3674        $y1 = $this->iy1 ;
     3675        $y2 = $this->iy2 ;
     3676
     3677        // Depending on if the target is below or above we have to
     3678        // handle thi different.
     3679        if( $y2 > $y1 ) {
     3680            $arrowtype = ARROW_DOWN;
     3681            $midy = round(($y2-$y1)/2+$y1);
     3682            if( $x2 > $x1 ) {
     3683                switch ( $this->iPathType  ) {
     3684                    case 0:
     3685                        $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
     3686                        break;
     3687                    case 1:
     3688                    case 2:
     3689                    case 3:
     3690                        $c = array($x1,$y1,$x2,$y1,$x2,$y2);
     3691                        break;
     3692                    default:
     3693                        JpGraphError::RaiseL(6032,$this->iPathType);
     3694//('Internal error: Unknown path type (='.$this->iPathType .') specified for link.');
     3695                        exit(1);
     3696                        break;
     3697                }
     3698            }
     3699            else {
     3700                switch ( $this->iPathType  ) {
     3701                    case 0:
     3702                    case 1:
     3703                        $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
     3704                        break;
     3705                    case 2:
     3706                        // Always extend out horizontally a bit from the first point
     3707                        // If we draw a link back in time (end to start) and the bars
     3708                        // are very close we also change the path so it comes in from
     3709                        // the left on the activity
     3710                        $c = array($x1,$y1,$x1+$this->iPathExtend,$y1,
     3711                                   $x1+$this->iPathExtend,$midy,
     3712                                   $x2,$midy,$x2,$y2);
     3713                        break;
     3714                    case 3:
     3715                        if( $y2-$midy < 6 ) {
     3716                            $c = array($x1,$y1,$x1,$midy,
     3717                                       $x2-$this->iPathExtend,$midy,
     3718                                       $x2-$this->iPathExtend,$y2,
     3719                                       $x2,$y2);
     3720                            $arrowtype = ARROW_RIGHT;
     3721                        }
     3722                        else {
     3723                            $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
     3724                        }
     3725                        break;
     3726                    default:
     3727                        JpGraphError::RaiseL(6032,$this->iPathType);
     3728//('Internal error: Unknown path type specified for link.');
     3729                        exit(1);
     3730                        break;
     3731                }
     3732            }
     3733            $arrow = new LinkArrow($x2,$y2,$arrowtype);
     3734        }
     3735        else {
     3736            // Y2 < Y1
     3737            $arrowtype = ARROW_UP;
     3738            $midy = round(($y1-$y2)/2+$y2);
     3739            if( $x2 > $x1 ) {
     3740                switch ( $this->iPathType  ) {
     3741                    case 0:
     3742                    case 1:
     3743                        $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
     3744                        break;
     3745                    case 3:
     3746                        if( $midy-$y2 < 8 ) {
     3747                            $arrowtype = ARROW_RIGHT;
     3748                            $c = array($x1,$y1,$x1,$y2,$x2,$y2);
     3749                        }
     3750                        else {
     3751                            $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
     3752                        }
     3753                        break;
     3754                    default:
     3755                        JpGraphError::RaiseL(6032,$this->iPathType);
     3756//('Internal error: Unknown path type specified for link.');
     3757                        break;
     3758                }
     3759            }
     3760            else {
     3761                switch ( $this->iPathType  ) {
     3762                    case 0:
     3763                    case 1:
     3764                        $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
     3765                        break;
     3766                    case 2:
     3767                        // Always extend out horizontally a bit from the first point
     3768                        $c = array($x1,$y1,$x1+$this->iPathExtend,$y1,
     3769                                   $x1+$this->iPathExtend,$midy,
     3770                                   $x2,$midy,$x2,$y2);
     3771                        break;
     3772                    case 3:
     3773                        if( $midy-$y2 < 16 ) {
     3774                            $arrowtype = ARROW_RIGHT;
     3775                            $c = array($x1,$y1,$x1,$midy,$x2-$this->iPathExtend,$midy,
     3776                                       $x2-$this->iPathExtend,$y2,
     3777                                       $x2,$y2);
     3778                        }
     3779                        else {
     3780                            $c = array($x1,$y1,$x1,$midy,$x2,$midy,$x2,$y2);
     3781                        }
     3782                        break;
     3783                    default:
     3784                        JpGraphError::RaiseL(6032,$this->iPathType);
     3785//('Internal error: Unknown path type specified for link.');
     3786                        break;
     3787                }
     3788            }
     3789            $arrow = new LinkArrow($x2,$y2,$arrowtype);
     3790        }
     3791        $aImg->SetColor($this->iColor);
     3792        $aImg->SetLineWeight($this->iWeight);
     3793        $aImg->Polygon($c);
     3794        $aImg->SetLineWeight(1);
     3795        $arrow->SetColor($this->iColor);
     3796        $arrow->SetSize($this->iArrowSize);
     3797        $arrow->SetType($this->iArrowType);
     3798        $arrow->Stroke($aImg);
    39513799    }
    39523800}
  • trunk/client/modules/Elezioni/grafici/jpgraph_gb2312.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_GB2312.PHP
    4 // Description: Chinese font conversions
    5 // Created:     2003-05-30
    6 // Ver:         $Id: jpgraph_gb2312.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        JPGRAPH_GB2312.PHP
     4// Description: PHP4 Graph Plotting library. Chinese font conversions
     5// Created:     2003-05-30
     6// Ver:         $Id: jpgraph_gb2312.php 781 2006-10-08 08:07:47Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
    1111
    1212class GB2312toUTF8 {
    13     // --------------------------------------------------------------------
    14     // This code table is used to translate GB2312 code (key) to
    15     // it's corresponding Unicode value (data)
    16     // --------------------------------------------------------------------
    17     private $codetable = array(
    18     8481 => 12288, 8482 => 12289, 8483 => 12290, 8484 => 12539, 8485 => 713,
    19     8486 => 711, 8487 => 168, 8488 => 12291, 8489 => 12293, 8490 => 8213,
    20     8491 => 65374, 8492 => 8214, 8493 => 8230, 8494 => 8216, 8495 => 8217,
    21     8496 => 8220, 8497 => 8221, 8498 => 12308, 8499 => 12309, 8500 => 12296,
    22     8501 => 12297, 8502 => 12298, 8503 => 12299, 8504 => 12300, 8505 => 12301,
    23     8506 => 12302, 8507 => 12303, 8508 => 12310, 8509 => 12311, 8510 => 12304,
    24     8511 => 12305, 8512 => 177, 8513 => 215, 8514 => 247, 8515 => 8758,
    25     8516 => 8743, 8517 => 8744, 8518 => 8721, 8519 => 8719, 8520 => 8746,
    26     8521 => 8745, 8522 => 8712, 8523 => 8759, 8524 => 8730, 8525 => 8869,
    27     8526 => 8741, 8527 => 8736, 8528 => 8978, 8529 => 8857, 8530 => 8747,
    28     8531 => 8750, 8532 => 8801, 8533 => 8780, 8534 => 8776, 8535 => 8765,
    29     8536 => 8733, 8537 => 8800, 8538 => 8814, 8539 => 8815, 8540 => 8804,
    30     8541 => 8805, 8542 => 8734, 8543 => 8757, 8544 => 8756, 8545 => 9794,
    31     8546 => 9792, 8547 => 176, 8548 => 8242, 8549 => 8243, 8550 => 8451,
    32     8551 => 65284, 8552 => 164, 8553 => 65504, 8554 => 65505, 8555 => 8240,
    33     8556 => 167, 8557 => 8470, 8558 => 9734, 8559 => 9733, 8560 => 9675,
    34     8561 => 9679, 8562 => 9678, 8563 => 9671, 8564 => 9670, 8565 => 9633,
    35     8566 => 9632, 8567 => 9651, 8568 => 9650, 8569 => 8251, 8570 => 8594,
    36     8571 => 8592, 8572 => 8593, 8573 => 8595, 8574 => 12307, 8753 => 9352,
    37     8754 => 9353, 8755 => 9354, 8756 => 9355, 8757 => 9356, 8758 => 9357,
    38     8759 => 9358, 8760 => 9359, 8761 => 9360, 8762 => 9361, 8763 => 9362,
    39     8764 => 9363, 8765 => 9364, 8766 => 9365, 8767 => 9366, 8768 => 9367,
    40     8769 => 9368, 8770 => 9369, 8771 => 9370, 8772 => 9371, 8773 => 9332,
    41     8774 => 9333, 8775 => 9334, 8776 => 9335, 8777 => 9336, 8778 => 9337,
    42     8779 => 9338, 8780 => 9339, 8781 => 9340, 8782 => 9341, 8783 => 9342,
    43     8784 => 9343, 8785 => 9344, 8786 => 9345, 8787 => 9346, 8788 => 9347,
    44     8789 => 9348, 8790 => 9349, 8791 => 9350, 8792 => 9351, 8793 => 9312,
    45     8794 => 9313, 8795 => 9314, 8796 => 9315, 8797 => 9316, 8798 => 9317,
    46     8799 => 9318, 8800 => 9319, 8801 => 9320, 8802 => 9321, 8805 => 12832,
    47     8806 => 12833, 8807 => 12834, 8808 => 12835, 8809 => 12836, 8810 => 12837,
    48     8811 => 12838, 8812 => 12839, 8813 => 12840, 8814 => 12841, 8817 => 8544,
    49     8818 => 8545, 8819 => 8546, 8820 => 8547, 8821 => 8548, 8822 => 8549,
    50     8823 => 8550, 8824 => 8551, 8825 => 8552, 8826 => 8553, 8827 => 8554,
    51     8828 => 8555, 8993 => 65281, 8994 => 65282, 8995 => 65283, 8996 => 65509,
    52     8997 => 65285, 8998 => 65286, 8999 => 65287, 9000 => 65288, 9001 => 65289,
    53     9002 => 65290, 9003 => 65291, 9004 => 65292, 9005 => 65293, 9006 => 65294,
    54     9007 => 65295, 9008 => 65296, 9009 => 65297, 9010 => 65298, 9011 => 65299,
    55     9012 => 65300, 9013 => 65301, 9014 => 65302, 9015 => 65303, 9016 => 65304,
    56     9017 => 65305, 9018 => 65306, 9019 => 65307, 9020 => 65308, 9021 => 65309,
    57     9022 => 65310, 9023 => 65311, 9024 => 65312, 9025 => 65313, 9026 => 65314,
    58     9027 => 65315, 9028 => 65316, 9029 => 65317, 9030 => 65318, 9031 => 65319,
    59     9032 => 65320, 9033 => 65321, 9034 => 65322, 9035 => 65323, 9036 => 65324,
    60     9037 => 65325, 9038 => 65326, 9039 => 65327, 9040 => 65328, 9041 => 65329,
    61     9042 => 65330, 9043 => 65331, 9044 => 65332, 9045 => 65333, 9046 => 65334,
    62     9047 => 65335, 9048 => 65336, 9049 => 65337, 9050 => 65338, 9051 => 65339,
    63     9052 => 65340, 9053 => 65341, 9054 => 65342, 9055 => 65343, 9056 => 65344,
    64     9057 => 65345, 9058 => 65346, 9059 => 65347, 9060 => 65348, 9061 => 65349,
    65     9062 => 65350, 9063 => 65351, 9064 => 65352, 9065 => 65353, 9066 => 65354,
    66     9067 => 65355, 9068 => 65356, 9069 => 65357, 9070 => 65358, 9071 => 65359,
    67     9072 => 65360, 9073 => 65361, 9074 => 65362, 9075 => 65363, 9076 => 65364,
    68     9077 => 65365, 9078 => 65366, 9079 => 65367, 9080 => 65368, 9081 => 65369,
    69     9082 => 65370, 9083 => 65371, 9084 => 65372, 9085 => 65373, 9086 => 65507,
    70     9249 => 12353, 9250 => 12354, 9251 => 12355, 9252 => 12356, 9253 => 12357,
    71     9254 => 12358, 9255 => 12359, 9256 => 12360, 9257 => 12361, 9258 => 12362,
    72     9259 => 12363, 9260 => 12364, 9261 => 12365, 9262 => 12366, 9263 => 12367,
    73     9264 => 12368, 9265 => 12369, 9266 => 12370, 9267 => 12371, 9268 => 12372,
    74     9269 => 12373, 9270 => 12374, 9271 => 12375, 9272 => 12376, 9273 => 12377,
    75     9274 => 12378, 9275 => 12379, 9276 => 12380, 9277 => 12381, 9278 => 12382,
    76     9279 => 12383, 9280 => 12384, 9281 => 12385, 9282 => 12386, 9283 => 12387,
    77     9284 => 12388, 9285 => 12389, 9286 => 12390, 9287 => 12391, 9288 => 12392,
    78     9289 => 12393, 9290 => 12394, 9291 => 12395, 9292 => 12396, 9293 => 12397,
    79     9294 => 12398, 9295 => 12399, 9296 => 12400, 9297 => 12401, 9298 => 12402,
    80     9299 => 12403, 9300 => 12404, 9301 => 12405, 9302 => 12406, 9303 => 12407,
    81     9304 => 12408, 9305 => 12409, 9306 => 12410, 9307 => 12411, 9308 => 12412,
    82     9309 => 12413, 9310 => 12414, 9311 => 12415, 9312 => 12416, 9313 => 12417,
    83     9314 => 12418, 9315 => 12419, 9316 => 12420, 9317 => 12421, 9318 => 12422,
    84     9319 => 12423, 9320 => 12424, 9321 => 12425, 9322 => 12426, 9323 => 12427,
    85     9324 => 12428, 9325 => 12429, 9326 => 12430, 9327 => 12431, 9328 => 12432,
    86     9329 => 12433, 9330 => 12434, 9331 => 12435, 9505 => 12449, 9506 => 12450,
    87     9507 => 12451, 9508 => 12452, 9509 => 12453, 9510 => 12454, 9511 => 12455,
    88     9512 => 12456, 9513 => 12457, 9514 => 12458, 9515 => 12459, 9516 => 12460,
    89     9517 => 12461, 9518 => 12462, 9519 => 12463, 9520 => 12464, 9521 => 12465,
    90     9522 => 12466, 9523 => 12467, 9524 => 12468, 9525 => 12469, 9526 => 12470,
    91     9527 => 12471, 9528 => 12472, 9529 => 12473, 9530 => 12474, 9531 => 12475,
    92     9532 => 12476, 9533 => 12477, 9534 => 12478, 9535 => 12479, 9536 => 12480,
    93     9537 => 12481, 9538 => 12482, 9539 => 12483, 9540 => 12484, 9541 => 12485,
    94     9542 => 12486, 9543 => 12487, 9544 => 12488, 9545 => 12489, 9546 => 12490,
    95     9547 => 12491, 9548 => 12492, 9549 => 12493, 9550 => 12494, 9551 => 12495,
    96     9552 => 12496, 9553 => 12497, 9554 => 12498, 9555 => 12499, 9556 => 12500,
    97     9557 => 12501, 9558 => 12502, 9559 => 12503, 9560 => 12504, 9561 => 12505,
    98     9562 => 12506, 9563 => 12507, 9564 => 12508, 9565 => 12509, 9566 => 12510,
    99     9567 => 12511, 9568 => 12512, 9569 => 12513, 9570 => 12514, 9571 => 12515,
    100     9572 => 12516, 9573 => 12517, 9574 => 12518, 9575 => 12519, 9576 => 12520,
    101     9577 => 12521, 9578 => 12522, 9579 => 12523, 9580 => 12524, 9581 => 12525,
    102     9582 => 12526, 9583 => 12527, 9584 => 12528, 9585 => 12529, 9586 => 12530,
    103     9587 => 12531, 9588 => 12532, 9589 => 12533, 9590 => 12534, 9761 => 913,
    104     9762 => 914, 9763 => 915, 9764 => 916, 9765 => 917, 9766 => 918,
    105     9767 => 919, 9768 => 920, 9769 => 921, 9770 => 922, 9771 => 923,
    106     9772 => 924, 9773 => 925, 9774 => 926, 9775 => 927, 9776 => 928,
    107     9777 => 929, 9778 => 931, 9779 => 932, 9780 => 933, 9781 => 934,
    108     9782 => 935, 9783 => 936, 9784 => 937, 9793 => 945, 9794 => 946,
    109     9795 => 947, 9796 => 948, 9797 => 949, 9798 => 950, 9799 => 951,
    110     9800 => 952, 9801 => 953, 9802 => 954, 9803 => 955, 9804 => 956,
    111     9805 => 957, 9806 => 958, 9807 => 959, 9808 => 960, 9809 => 961,
    112     9810 => 963, 9811 => 964, 9812 => 965, 9813 => 966, 9814 => 967,
    113     9815 => 968, 9816 => 969, 10017 => 1040, 10018 => 1041, 10019 => 1042,
    114     10020 => 1043, 10021 => 1044, 10022 => 1045, 10023 => 1025, 10024 => 1046,
    115     10025 => 1047, 10026 => 1048, 10027 => 1049, 10028 => 1050, 10029 => 1051,
    116     10030 => 1052, 10031 => 1053, 10032 => 1054, 10033 => 1055, 10034 => 1056,
    117     10035 => 1057, 10036 => 1058, 10037 => 1059, 10038 => 1060, 10039 => 1061,
    118     10040 => 1062, 10041 => 1063, 10042 => 1064, 10043 => 1065, 10044 => 1066,
    119     10045 => 1067, 10046 => 1068, 10047 => 1069, 10048 => 1070, 10049 => 1071,
    120     10065 => 1072, 10066 => 1073, 10067 => 1074, 10068 => 1075, 10069 => 1076,
    121     10070 => 1077, 10071 => 1105, 10072 => 1078, 10073 => 1079, 10074 => 1080,
    122     10075 => 1081, 10076 => 1082, 10077 => 1083, 10078 => 1084, 10079 => 1085,
    123     10080 => 1086, 10081 => 1087, 10082 => 1088, 10083 => 1089, 10084 => 1090,
    124     10085 => 1091, 10086 => 1092, 10087 => 1093, 10088 => 1094, 10089 => 1095,
    125     10090 => 1096, 10091 => 1097, 10092 => 1098, 10093 => 1099, 10094 => 1100,
    126     10095 => 1101, 10096 => 1102, 10097 => 1103, 10273 => 257, 10274 => 225,
    127     10275 => 462, 10276 => 224, 10277 => 275, 10278 => 233, 10279 => 283,
    128     10280 => 232, 10281 => 299, 10282 => 237, 10283 => 464, 10284 => 236,
    129     10285 => 333, 10286 => 243, 10287 => 466, 10288 => 242, 10289 => 363,
    130     10290 => 250, 10291 => 468, 10292 => 249, 10293 => 470, 10294 => 472,
    131     10295 => 474, 10296 => 476, 10297 => 252, 10298 => 234, 10309 => 12549,
    132     10310 => 12550, 10311 => 12551, 10312 => 12552, 10313 => 12553, 10314 => 12554,
    133     10315 => 12555, 10316 => 12556, 10317 => 12557, 10318 => 12558, 10319 => 12559,
    134     10320 => 12560, 10321 => 12561, 10322 => 12562, 10323 => 12563, 10324 => 12564,
    135     10325 => 12565, 10326 => 12566, 10327 => 12567, 10328 => 12568, 10329 => 12569,
    136     10330 => 12570, 10331 => 12571, 10332 => 12572, 10333 => 12573, 10334 => 12574,
    137     10335 => 12575, 10336 => 12576, 10337 => 12577, 10338 => 12578, 10339 => 12579,
    138     10340 => 12580, 10341 => 12581, 10342 => 12582, 10343 => 12583, 10344 => 12584,
    139     10345 => 12585, 10532 => 9472, 10533 => 9473, 10534 => 9474, 10535 => 9475,
    140     10536 => 9476, 10537 => 9477, 10538 => 9478, 10539 => 9479, 10540 => 9480,
    141     10541 => 9481, 10542 => 9482, 10543 => 9483, 10544 => 9484, 10545 => 9485,
    142     10546 => 9486, 10547 => 9487, 10548 => 9488, 10549 => 9489, 10550 => 9490,
    143     10551 => 9491, 10552 => 9492, 10553 => 9493, 10554 => 9494, 10555 => 9495,
    144     10556 => 9496, 10557 => 9497, 10558 => 9498, 10559 => 9499, 10560 => 9500,
    145     10561 => 9501, 10562 => 9502, 10563 => 9503, 10564 => 9504, 10565 => 9505,
    146     10566 => 9506, 10567 => 9507, 10568 => 9508, 10569 => 9509, 10570 => 9510,
    147     10571 => 9511, 10572 => 9512, 10573 => 9513, 10574 => 9514, 10575 => 9515,
    148     10576 => 9516, 10577 => 9517, 10578 => 9518, 10579 => 9519, 10580 => 9520,
    149     10581 => 9521, 10582 => 9522, 10583 => 9523, 10584 => 9524, 10585 => 9525,
    150     10586 => 9526, 10587 => 9527, 10588 => 9528, 10589 => 9529, 10590 => 9530,
    151     10591 => 9531, 10592 => 9532, 10593 => 9533, 10594 => 9534, 10595 => 9535,
    152     10596 => 9536, 10597 => 9537, 10598 => 9538, 10599 => 9539, 10600 => 9540,
    153     10601 => 9541, 10602 => 9542, 10603 => 9543, 10604 => 9544, 10605 => 9545,
    154     10606 => 9546, 10607 => 9547, 12321 => 21834, 12322 => 38463, 12323 => 22467,
    155     12324 => 25384, 12325 => 21710, 12326 => 21769, 12327 => 21696, 12328 => 30353,
    156     12329 => 30284, 12330 => 34108, 12331 => 30702, 12332 => 33406, 12333 => 30861,
    157     12334 => 29233, 12335 => 38552, 12336 => 38797, 12337 => 27688, 12338 => 23433,
    158     12339 => 20474, 12340 => 25353, 12341 => 26263, 12342 => 23736, 12343 => 33018,
    159     12344 => 26696, 12345 => 32942, 12346 => 26114, 12347 => 30414, 12348 => 20985,
    160     12349 => 25942, 12350 => 29100, 12351 => 32753, 12352 => 34948, 12353 => 20658,
    161     12354 => 22885, 12355 => 25034, 12356 => 28595, 12357 => 33453, 12358 => 25420,
    162     12359 => 25170, 12360 => 21485, 12361 => 21543, 12362 => 31494, 12363 => 20843,
    163     12364 => 30116, 12365 => 24052, 12366 => 25300, 12367 => 36299, 12368 => 38774,
    164     12369 => 25226, 12370 => 32793, 12371 => 22365, 12372 => 38712, 12373 => 32610,
    165     12374 => 29240, 12375 => 30333, 12376 => 26575, 12377 => 30334, 12378 => 25670,
    166     12379 => 20336, 12380 => 36133, 12381 => 25308, 12382 => 31255, 12383 => 26001,
    167     12384 => 29677, 12385 => 25644, 12386 => 25203, 12387 => 33324, 12388 => 39041,
    168     12389 => 26495, 12390 => 29256, 12391 => 25198, 12392 => 25292, 12393 => 20276,
    169     12394 => 29923, 12395 => 21322, 12396 => 21150, 12397 => 32458, 12398 => 37030,
    170     12399 => 24110, 12400 => 26758, 12401 => 27036, 12402 => 33152, 12403 => 32465,
    171     12404 => 26834, 12405 => 30917, 12406 => 34444, 12407 => 38225, 12408 => 20621,
    172     12409 => 35876, 12410 => 33502, 12411 => 32990, 12412 => 21253, 12413 => 35090,
    173     12414 => 21093, 12577 => 34180, 12578 => 38649, 12579 => 20445, 12580 => 22561,
    174     12581 => 39281, 12582 => 23453, 12583 => 25265, 12584 => 25253, 12585 => 26292,
    175     12586 => 35961, 12587 => 40077, 12588 => 29190, 12589 => 26479, 12590 => 30865,
    176     12591 => 24754, 12592 => 21329, 12593 => 21271, 12594 => 36744, 12595 => 32972,
    177     12596 => 36125, 12597 => 38049, 12598 => 20493, 12599 => 29384, 12600 => 22791,
    178     12601 => 24811, 12602 => 28953, 12603 => 34987, 12604 => 22868, 12605 => 33519,
    179     12606 => 26412, 12607 => 31528, 12608 => 23849, 12609 => 32503, 12610 => 29997,
    180     12611 => 27893, 12612 => 36454, 12613 => 36856, 12614 => 36924, 12615 => 40763,
    181     12616 => 27604, 12617 => 37145, 12618 => 31508, 12619 => 24444, 12620 => 30887,
    182     12621 => 34006, 12622 => 34109, 12623 => 27605, 12624 => 27609, 12625 => 27606,
    183     12626 => 24065, 12627 => 24199, 12628 => 30201, 12629 => 38381, 12630 => 25949,
    184     12631 => 24330, 12632 => 24517, 12633 => 36767, 12634 => 22721, 12635 => 33218,
    185     12636 => 36991, 12637 => 38491, 12638 => 38829, 12639 => 36793, 12640 => 32534,
    186     12641 => 36140, 12642 => 25153, 12643 => 20415, 12644 => 21464, 12645 => 21342,
    187     12646 => 36776, 12647 => 36777, 12648 => 36779, 12649 => 36941, 12650 => 26631,
    188     12651 => 24426, 12652 => 33176, 12653 => 34920, 12654 => 40150, 12655 => 24971,
    189     12656 => 21035, 12657 => 30250, 12658 => 24428, 12659 => 25996, 12660 => 28626,
    190     12661 => 28392, 12662 => 23486, 12663 => 25672, 12664 => 20853, 12665 => 20912,
    191     12666 => 26564, 12667 => 19993, 12668 => 31177, 12669 => 39292, 12670 => 28851,
    192     12833 => 30149, 12834 => 24182, 12835 => 29627, 12836 => 33760, 12837 => 25773,
    193     12838 => 25320, 12839 => 38069, 12840 => 27874, 12841 => 21338, 12842 => 21187,
    194     12843 => 25615, 12844 => 38082, 12845 => 31636, 12846 => 20271, 12847 => 24091,
    195     12848 => 33334, 12849 => 33046, 12850 => 33162, 12851 => 28196, 12852 => 27850,
    196     12853 => 39539, 12854 => 25429, 12855 => 21340, 12856 => 21754, 12857 => 34917,
    197     12858 => 22496, 12859 => 19981, 12860 => 24067, 12861 => 27493, 12862 => 31807,
    198     12863 => 37096, 12864 => 24598, 12865 => 25830, 12866 => 29468, 12867 => 35009,
    199     12868 => 26448, 12869 => 25165, 12870 => 36130, 12871 => 30572, 12872 => 36393,
    200     12873 => 37319, 12874 => 24425, 12875 => 33756, 12876 => 34081, 12877 => 39184,
    201     12878 => 21442, 12879 => 34453, 12880 => 27531, 12881 => 24813, 12882 => 24808,
    202     12883 => 28799, 12884 => 33485, 12885 => 33329, 12886 => 20179, 12887 => 27815,
    203     12888 => 34255, 12889 => 25805, 12890 => 31961, 12891 => 27133, 12892 => 26361,
    204     12893 => 33609, 12894 => 21397, 12895 => 31574, 12896 => 20391, 12897 => 20876,
    205     12898 => 27979, 12899 => 23618, 12900 => 36461, 12901 => 25554, 12902 => 21449,
    206     12903 => 33580, 12904 => 33590, 12905 => 26597, 12906 => 30900, 12907 => 25661,
    207     12908 => 23519, 12909 => 23700, 12910 => 24046, 12911 => 35815, 12912 => 25286,
    208     12913 => 26612, 12914 => 35962, 12915 => 25600, 12916 => 25530, 12917 => 34633,
    209     12918 => 39307, 12919 => 35863, 12920 => 32544, 12921 => 38130, 12922 => 20135,
    210     12923 => 38416, 12924 => 39076, 12925 => 26124, 12926 => 29462, 13089 => 22330,
    211     13090 => 23581, 13091 => 24120, 13092 => 38271, 13093 => 20607, 13094 => 32928,
    212     13095 => 21378, 13096 => 25950, 13097 => 30021, 13098 => 21809, 13099 => 20513,
    213     13100 => 36229, 13101 => 25220, 13102 => 38046, 13103 => 26397, 13104 => 22066,
    214     13105 => 28526, 13106 => 24034, 13107 => 21557, 13108 => 28818, 13109 => 36710,
    215     13110 => 25199, 13111 => 25764, 13112 => 25507, 13113 => 24443, 13114 => 28552,
    216     13115 => 37108, 13116 => 33251, 13117 => 36784, 13118 => 23576, 13119 => 26216,
    217     13120 => 24561, 13121 => 27785, 13122 => 38472, 13123 => 36225, 13124 => 34924,
    218     13125 => 25745, 13126 => 31216, 13127 => 22478, 13128 => 27225, 13129 => 25104,
    219     13130 => 21576, 13131 => 20056, 13132 => 31243, 13133 => 24809, 13134 => 28548,
    220     13135 => 35802, 13136 => 25215, 13137 => 36894, 13138 => 39563, 13139 => 31204,
    221     13140 => 21507, 13141 => 30196, 13142 => 25345, 13143 => 21273, 13144 => 27744,
    222     13145 => 36831, 13146 => 24347, 13147 => 39536, 13148 => 32827, 13149 => 40831,
    223     13150 => 20360, 13151 => 23610, 13152 => 36196, 13153 => 32709, 13154 => 26021,
    224     13155 => 28861, 13156 => 20805, 13157 => 20914, 13158 => 34411, 13159 => 23815,
    225     13160 => 23456, 13161 => 25277, 13162 => 37228, 13163 => 30068, 13164 => 36364,
    226     13165 => 31264, 13166 => 24833, 13167 => 31609, 13168 => 20167, 13169 => 32504,
    227     13170 => 30597, 13171 => 19985, 13172 => 33261, 13173 => 21021, 13174 => 20986,
    228     13175 => 27249, 13176 => 21416, 13177 => 36487, 13178 => 38148, 13179 => 38607,
    229     13180 => 28353, 13181 => 38500, 13182 => 26970, 13345 => 30784, 13346 => 20648,
    230     13347 => 30679, 13348 => 25616, 13349 => 35302, 13350 => 22788, 13351 => 25571,
    231     13352 => 24029, 13353 => 31359, 13354 => 26941, 13355 => 20256, 13356 => 33337,
    232     13357 => 21912, 13358 => 20018, 13359 => 30126, 13360 => 31383, 13361 => 24162,
    233     13362 => 24202, 13363 => 38383, 13364 => 21019, 13365 => 21561, 13366 => 28810,
    234     13367 => 25462, 13368 => 38180, 13369 => 22402, 13370 => 26149, 13371 => 26943,
    235     13372 => 37255, 13373 => 21767, 13374 => 28147, 13375 => 32431, 13376 => 34850,
    236     13377 => 25139, 13378 => 32496, 13379 => 30133, 13380 => 33576, 13381 => 30913,
    237     13382 => 38604, 13383 => 36766, 13384 => 24904, 13385 => 29943, 13386 => 35789,
    238     13387 => 27492, 13388 => 21050, 13389 => 36176, 13390 => 27425, 13391 => 32874,
    239     13392 => 33905, 13393 => 22257, 13394 => 21254, 13395 => 20174, 13396 => 19995,
    240     13397 => 20945, 13398 => 31895, 13399 => 37259, 13400 => 31751, 13401 => 20419,
    241     13402 => 36479, 13403 => 31713, 13404 => 31388, 13405 => 25703, 13406 => 23828,
    242     13407 => 20652, 13408 => 33030, 13409 => 30209, 13410 => 31929, 13411 => 28140,
    243     13412 => 32736, 13413 => 26449, 13414 => 23384, 13415 => 23544, 13416 => 30923,
    244     13417 => 25774, 13418 => 25619, 13419 => 25514, 13420 => 25387, 13421 => 38169,
    245     13422 => 25645, 13423 => 36798, 13424 => 31572, 13425 => 30249, 13426 => 25171,
    246     13427 => 22823, 13428 => 21574, 13429 => 27513, 13430 => 20643, 13431 => 25140,
    247     13432 => 24102, 13433 => 27526, 13434 => 20195, 13435 => 36151, 13436 => 34955,
    248     13437 => 24453, 13438 => 36910, 13601 => 24608, 13602 => 32829, 13603 => 25285,
    249     13604 => 20025, 13605 => 21333, 13606 => 37112, 13607 => 25528, 13608 => 32966,
    250     13609 => 26086, 13610 => 27694, 13611 => 20294, 13612 => 24814, 13613 => 28129,
    251     13614 => 35806, 13615 => 24377, 13616 => 34507, 13617 => 24403, 13618 => 25377,
    252     13619 => 20826, 13620 => 33633, 13621 => 26723, 13622 => 20992, 13623 => 25443,
    253     13624 => 36424, 13625 => 20498, 13626 => 23707, 13627 => 31095, 13628 => 23548,
    254     13629 => 21040, 13630 => 31291, 13631 => 24764, 13632 => 36947, 13633 => 30423,
    255     13634 => 24503, 13635 => 24471, 13636 => 30340, 13637 => 36460, 13638 => 28783,
    256     13639 => 30331, 13640 => 31561, 13641 => 30634, 13642 => 20979, 13643 => 37011,
    257     13644 => 22564, 13645 => 20302, 13646 => 28404, 13647 => 36842, 13648 => 25932,
    258     13649 => 31515, 13650 => 29380, 13651 => 28068, 13652 => 32735, 13653 => 23265,
    259     13654 => 25269, 13655 => 24213, 13656 => 22320, 13657 => 33922, 13658 => 31532,
    260     13659 => 24093, 13660 => 24351, 13661 => 36882, 13662 => 32532, 13663 => 39072,
    261     13664 => 25474, 13665 => 28359, 13666 => 30872, 13667 => 28857, 13668 => 20856,
    262     13669 => 38747, 13670 => 22443, 13671 => 30005, 13672 => 20291, 13673 => 30008,
    263     13674 => 24215, 13675 => 24806, 13676 => 22880, 13677 => 28096, 13678 => 27583,
    264     13679 => 30857, 13680 => 21500, 13681 => 38613, 13682 => 20939, 13683 => 20993,
    265     13684 => 25481, 13685 => 21514, 13686 => 38035, 13687 => 35843, 13688 => 36300,
    266     13689 => 29241, 13690 => 30879, 13691 => 34678, 13692 => 36845, 13693 => 35853,
    267     13694 => 21472, 13857 => 19969, 13858 => 30447, 13859 => 21486, 13860 => 38025,
    268     13861 => 39030, 13862 => 40718, 13863 => 38189, 13864 => 23450, 13865 => 35746,
    269     13866 => 20002, 13867 => 19996, 13868 => 20908, 13869 => 33891, 13870 => 25026,
    270     13871 => 21160, 13872 => 26635, 13873 => 20375, 13874 => 24683, 13875 => 20923,
    271     13876 => 27934, 13877 => 20828, 13878 => 25238, 13879 => 26007, 13880 => 38497,
    272     13881 => 35910, 13882 => 36887, 13883 => 30168, 13884 => 37117, 13885 => 30563,
    273     13886 => 27602, 13887 => 29322, 13888 => 29420, 13889 => 35835, 13890 => 22581,
    274     13891 => 30585, 13892 => 36172, 13893 => 26460, 13894 => 38208, 13895 => 32922,
    275     13896 => 24230, 13897 => 28193, 13898 => 22930, 13899 => 31471, 13900 => 30701,
    276     13901 => 38203, 13902 => 27573, 13903 => 26029, 13904 => 32526, 13905 => 22534,
    277     13906 => 20817, 13907 => 38431, 13908 => 23545, 13909 => 22697, 13910 => 21544,
    278     13911 => 36466, 13912 => 25958, 13913 => 39039, 13914 => 22244, 13915 => 38045,
    279     13916 => 30462, 13917 => 36929, 13918 => 25479, 13919 => 21702, 13920 => 22810,
    280     13921 => 22842, 13922 => 22427, 13923 => 36530, 13924 => 26421, 13925 => 36346,
    281     13926 => 33333, 13927 => 21057, 13928 => 24816, 13929 => 22549, 13930 => 34558,
    282     13931 => 23784, 13932 => 40517, 13933 => 20420, 13934 => 39069, 13935 => 35769,
    283     13936 => 23077, 13937 => 24694, 13938 => 21380, 13939 => 25212, 13940 => 36943,
    284     13941 => 37122, 13942 => 39295, 13943 => 24681, 13944 => 32780, 13945 => 20799,
    285     13946 => 32819, 13947 => 23572, 13948 => 39285, 13949 => 27953, 13950 => 20108,
    286     14113 => 36144, 14114 => 21457, 14115 => 32602, 14116 => 31567, 14117 => 20240,
    287     14118 => 20047, 14119 => 38400, 14120 => 27861, 14121 => 29648, 14122 => 34281,
    288     14123 => 24070, 14124 => 30058, 14125 => 32763, 14126 => 27146, 14127 => 30718,
    289     14128 => 38034, 14129 => 32321, 14130 => 20961, 14131 => 28902, 14132 => 21453,
    290     14133 => 36820, 14134 => 33539, 14135 => 36137, 14136 => 29359, 14137 => 39277,
    291     14138 => 27867, 14139 => 22346, 14140 => 33459, 14141 => 26041, 14142 => 32938,
    292     14143 => 25151, 14144 => 38450, 14145 => 22952, 14146 => 20223, 14147 => 35775,
    293     14148 => 32442, 14149 => 25918, 14150 => 33778, 14151 => 38750, 14152 => 21857,
    294     14153 => 39134, 14154 => 32933, 14155 => 21290, 14156 => 35837, 14157 => 21536,
    295     14158 => 32954, 14159 => 24223, 14160 => 27832, 14161 => 36153, 14162 => 33452,
    296     14163 => 37210, 14164 => 21545, 14165 => 27675, 14166 => 20998, 14167 => 32439,
    297     14168 => 22367, 14169 => 28954, 14170 => 27774, 14171 => 31881, 14172 => 22859,
    298     14173 => 20221, 14174 => 24575, 14175 => 24868, 14176 => 31914, 14177 => 20016,
    299     14178 => 23553, 14179 => 26539, 14180 => 34562, 14181 => 23792, 14182 => 38155,
    300     14183 => 39118, 14184 => 30127, 14185 => 28925, 14186 => 36898, 14187 => 20911,
    301     14188 => 32541, 14189 => 35773, 14190 => 22857, 14191 => 20964, 14192 => 20315,
    302     14193 => 21542, 14194 => 22827, 14195 => 25975, 14196 => 32932, 14197 => 23413,
    303     14198 => 25206, 14199 => 25282, 14200 => 36752, 14201 => 24133, 14202 => 27679,
    304     14203 => 31526, 14204 => 20239, 14205 => 20440, 14206 => 26381, 14369 => 28014,
    305     14370 => 28074, 14371 => 31119, 14372 => 34993, 14373 => 24343, 14374 => 29995,
    306     14375 => 25242, 14376 => 36741, 14377 => 20463, 14378 => 37340, 14379 => 26023,
    307     14380 => 33071, 14381 => 33105, 14382 => 24220, 14383 => 33104, 14384 => 36212,
    308     14385 => 21103, 14386 => 35206, 14387 => 36171, 14388 => 22797, 14389 => 20613,
    309     14390 => 20184, 14391 => 38428, 14392 => 29238, 14393 => 33145, 14394 => 36127,
    310     14395 => 23500, 14396 => 35747, 14397 => 38468, 14398 => 22919, 14399 => 32538,
    311     14400 => 21648, 14401 => 22134, 14402 => 22030, 14403 => 35813, 14404 => 25913,
    312     14405 => 27010, 14406 => 38041, 14407 => 30422, 14408 => 28297, 14409 => 24178,
    313     14410 => 29976, 14411 => 26438, 14412 => 26577, 14413 => 31487, 14414 => 32925,
    314     14415 => 36214, 14416 => 24863, 14417 => 31174, 14418 => 25954, 14419 => 36195,
    315     14420 => 20872, 14421 => 21018, 14422 => 38050, 14423 => 32568, 14424 => 32923,
    316     14425 => 32434, 14426 => 23703, 14427 => 28207, 14428 => 26464, 14429 => 31705,
    317     14430 => 30347, 14431 => 39640, 14432 => 33167, 14433 => 32660, 14434 => 31957,
    318     14435 => 25630, 14436 => 38224, 14437 => 31295, 14438 => 21578, 14439 => 21733,
    319     14440 => 27468, 14441 => 25601, 14442 => 25096, 14443 => 40509, 14444 => 33011,
    320     14445 => 30105, 14446 => 21106, 14447 => 38761, 14448 => 33883, 14449 => 26684,
    321     14450 => 34532, 14451 => 38401, 14452 => 38548, 14453 => 38124, 14454 => 20010,
    322     14455 => 21508, 14456 => 32473, 14457 => 26681, 14458 => 36319, 14459 => 32789,
    323     14460 => 26356, 14461 => 24218, 14462 => 32697, 14625 => 22466, 14626 => 32831,
    324     14627 => 26775, 14628 => 24037, 14629 => 25915, 14630 => 21151, 14631 => 24685,
    325     14632 => 40858, 14633 => 20379, 14634 => 36524, 14635 => 20844, 14636 => 23467,
    326     14637 => 24339, 14638 => 24041, 14639 => 27742, 14640 => 25329, 14641 => 36129,
    327     14642 => 20849, 14643 => 38057, 14644 => 21246, 14645 => 27807, 14646 => 33503,
    328     14647 => 29399, 14648 => 22434, 14649 => 26500, 14650 => 36141, 14651 => 22815,
    329     14652 => 36764, 14653 => 33735, 14654 => 21653, 14655 => 31629, 14656 => 20272,
    330     14657 => 27837, 14658 => 23396, 14659 => 22993, 14660 => 40723, 14661 => 21476,
    331     14662 => 34506, 14663 => 39592, 14664 => 35895, 14665 => 32929, 14666 => 25925,
    332     14667 => 39038, 14668 => 22266, 14669 => 38599, 14670 => 21038, 14671 => 29916,
    333     14672 => 21072, 14673 => 23521, 14674 => 25346, 14675 => 35074, 14676 => 20054,
    334     14677 => 25296, 14678 => 24618, 14679 => 26874, 14680 => 20851, 14681 => 23448,
    335     14682 => 20896, 14683 => 35266, 14684 => 31649, 14685 => 39302, 14686 => 32592,
    336     14687 => 24815, 14688 => 28748, 14689 => 36143, 14690 => 20809, 14691 => 24191,
    337     14692 => 36891, 14693 => 29808, 14694 => 35268, 14695 => 22317, 14696 => 30789,
    338     14697 => 24402, 14698 => 40863, 14699 => 38394, 14700 => 36712, 14701 => 39740,
    339     14702 => 35809, 14703 => 30328, 14704 => 26690, 14705 => 26588, 14706 => 36330,
    340     14707 => 36149, 14708 => 21053, 14709 => 36746, 14710 => 28378, 14711 => 26829,
    341     14712 => 38149, 14713 => 37101, 14714 => 22269, 14715 => 26524, 14716 => 35065,
    342     14717 => 36807, 14718 => 21704, 14881 => 39608, 14882 => 23401, 14883 => 28023,
    343     14884 => 27686, 14885 => 20133, 14886 => 23475, 14887 => 39559, 14888 => 37219,
    344     14889 => 25000, 14890 => 37039, 14891 => 38889, 14892 => 21547, 14893 => 28085,
    345     14894 => 23506, 14895 => 20989, 14896 => 21898, 14897 => 32597, 14898 => 32752,
    346     14899 => 25788, 14900 => 25421, 14901 => 26097, 14902 => 25022, 14903 => 24717,
    347     14904 => 28938, 14905 => 27735, 14906 => 27721, 14907 => 22831, 14908 => 26477,
    348     14909 => 33322, 14910 => 22741, 14911 => 22158, 14912 => 35946, 14913 => 27627,
    349     14914 => 37085, 14915 => 22909, 14916 => 32791, 14917 => 21495, 14918 => 28009,
    350     14919 => 21621, 14920 => 21917, 14921 => 33655, 14922 => 33743, 14923 => 26680,
    351     14924 => 31166, 14925 => 21644, 14926 => 20309, 14927 => 21512, 14928 => 30418,
    352     14929 => 35977, 14930 => 38402, 14931 => 27827, 14932 => 28088, 14933 => 36203,
    353     14934 => 35088, 14935 => 40548, 14936 => 36154, 14937 => 22079, 14938 => 40657,
    354     14939 => 30165, 14940 => 24456, 14941 => 29408, 14942 => 24680, 14943 => 21756,
    355     14944 => 20136, 14945 => 27178, 14946 => 34913, 14947 => 24658, 14948 => 36720,
    356     14949 => 21700, 14950 => 28888, 14951 => 34425, 14952 => 40511, 14953 => 27946,
    357     14954 => 23439, 14955 => 24344, 14956 => 32418, 14957 => 21897, 14958 => 20399,
    358     14959 => 29492, 14960 => 21564, 14961 => 21402, 14962 => 20505, 14963 => 21518,
    359     14964 => 21628, 14965 => 20046, 14966 => 24573, 14967 => 29786, 14968 => 22774,
    360     14969 => 33899, 14970 => 32993, 14971 => 34676, 14972 => 29392, 14973 => 31946,
    361     14974 => 28246, 15137 => 24359, 15138 => 34382, 15139 => 21804, 15140 => 25252,
    362     15141 => 20114, 15142 => 27818, 15143 => 25143, 15144 => 33457, 15145 => 21719,
    363     15146 => 21326, 15147 => 29502, 15148 => 28369, 15149 => 30011, 15150 => 21010,
    364     15151 => 21270, 15152 => 35805, 15153 => 27088, 15154 => 24458, 15155 => 24576,
    365     15156 => 28142, 15157 => 22351, 15158 => 27426, 15159 => 29615, 15160 => 26707,
    366     15161 => 36824, 15162 => 32531, 15163 => 25442, 15164 => 24739, 15165 => 21796,
    367     15166 => 30186, 15167 => 35938, 15168 => 28949, 15169 => 28067, 15170 => 23462,
    368     15171 => 24187, 15172 => 33618, 15173 => 24908, 15174 => 40644, 15175 => 30970,
    369     15176 => 34647, 15177 => 31783, 15178 => 30343, 15179 => 20976, 15180 => 24822,
    370     15181 => 29004, 15182 => 26179, 15183 => 24140, 15184 => 24653, 15185 => 35854,
    371     15186 => 28784, 15187 => 25381, 15188 => 36745, 15189 => 24509, 15190 => 24674,
    372     15191 => 34516, 15192 => 22238, 15193 => 27585, 15194 => 24724, 15195 => 24935,
    373     15196 => 21321, 15197 => 24800, 15198 => 26214, 15199 => 36159, 15200 => 31229,
    374     15201 => 20250, 15202 => 28905, 15203 => 27719, 15204 => 35763, 15205 => 35826,
    375     15206 => 32472, 15207 => 33636, 15208 => 26127, 15209 => 23130, 15210 => 39746,
    376     15211 => 27985, 15212 => 28151, 15213 => 35905, 15214 => 27963, 15215 => 20249,
    377     15216 => 28779, 15217 => 33719, 15218 => 25110, 15219 => 24785, 15220 => 38669,
    378     15221 => 36135, 15222 => 31096, 15223 => 20987, 15224 => 22334, 15225 => 22522,
    379     15226 => 26426, 15227 => 30072, 15228 => 31293, 15229 => 31215, 15230 => 31637,
    380     15393 => 32908, 15394 => 39269, 15395 => 36857, 15396 => 28608, 15397 => 35749,
    381     15398 => 40481, 15399 => 23020, 15400 => 32489, 15401 => 32521, 15402 => 21513,
    382     15403 => 26497, 15404 => 26840, 15405 => 36753, 15406 => 31821, 15407 => 38598,
    383     15408 => 21450, 15409 => 24613, 15410 => 30142, 15411 => 27762, 15412 => 21363,
    384     15413 => 23241, 15414 => 32423, 15415 => 25380, 15416 => 20960, 15417 => 33034,
    385     15418 => 24049, 15419 => 34015, 15420 => 25216, 15421 => 20864, 15422 => 23395,
    386     15423 => 20238, 15424 => 31085, 15425 => 21058, 15426 => 24760, 15427 => 27982,
    387     15428 => 23492, 15429 => 23490, 15430 => 35745, 15431 => 35760, 15432 => 26082,
    388     15433 => 24524, 15434 => 38469, 15435 => 22931, 15436 => 32487, 15437 => 32426,
    389     15438 => 22025, 15439 => 26551, 15440 => 22841, 15441 => 20339, 15442 => 23478,
    390     15443 => 21152, 15444 => 33626, 15445 => 39050, 15446 => 36158, 15447 => 30002,
    391     15448 => 38078, 15449 => 20551, 15450 => 31292, 15451 => 20215, 15452 => 26550,
    392     15453 => 39550, 15454 => 23233, 15455 => 27516, 15456 => 30417, 15457 => 22362,
    393     15458 => 23574, 15459 => 31546, 15460 => 38388, 15461 => 29006, 15462 => 20860,
    394     15463 => 32937, 15464 => 33392, 15465 => 22904, 15466 => 32516, 15467 => 33575,
    395     15468 => 26816, 15469 => 26604, 15470 => 30897, 15471 => 30839, 15472 => 25315,
    396     15473 => 25441, 15474 => 31616, 15475 => 20461, 15476 => 21098, 15477 => 20943,
    397     15478 => 33616, 15479 => 27099, 15480 => 37492, 15481 => 36341, 15482 => 36145,
    398     15483 => 35265, 15484 => 38190, 15485 => 31661, 15486 => 20214, 15649 => 20581,
    399     15650 => 33328, 15651 => 21073, 15652 => 39279, 15653 => 28176, 15654 => 28293,
    400     15655 => 28071, 15656 => 24314, 15657 => 20725, 15658 => 23004, 15659 => 23558,
    401     15660 => 27974, 15661 => 27743, 15662 => 30086, 15663 => 33931, 15664 => 26728,
    402     15665 => 22870, 15666 => 35762, 15667 => 21280, 15668 => 37233, 15669 => 38477,
    403     15670 => 34121, 15671 => 26898, 15672 => 30977, 15673 => 28966, 15674 => 33014,
    404     15675 => 20132, 15676 => 37066, 15677 => 27975, 15678 => 39556, 15679 => 23047,
    405     15680 => 22204, 15681 => 25605, 15682 => 38128, 15683 => 30699, 15684 => 20389,
    406     15685 => 33050, 15686 => 29409, 15687 => 35282, 15688 => 39290, 15689 => 32564,
    407     15690 => 32478, 15691 => 21119, 15692 => 25945, 15693 => 37237, 15694 => 36735,
    408     15695 => 36739, 15696 => 21483, 15697 => 31382, 15698 => 25581, 15699 => 25509,
    409     15700 => 30342, 15701 => 31224, 15702 => 34903, 15703 => 38454, 15704 => 25130,
    410     15705 => 21163, 15706 => 33410, 15707 => 26708, 15708 => 26480, 15709 => 25463,
    411     15710 => 30571, 15711 => 31469, 15712 => 27905, 15713 => 32467, 15714 => 35299,
    412     15715 => 22992, 15716 => 25106, 15717 => 34249, 15718 => 33445, 15719 => 30028,
    413     15720 => 20511, 15721 => 20171, 15722 => 30117, 15723 => 35819, 15724 => 23626,
    414     15725 => 24062, 15726 => 31563, 15727 => 26020, 15728 => 37329, 15729 => 20170,
    415     15730 => 27941, 15731 => 35167, 15732 => 32039, 15733 => 38182, 15734 => 20165,
    416     15735 => 35880, 15736 => 36827, 15737 => 38771, 15738 => 26187, 15739 => 31105,
    417     15740 => 36817, 15741 => 28908, 15742 => 28024, 15905 => 23613, 15906 => 21170,
    418     15907 => 33606, 15908 => 20834, 15909 => 33550, 15910 => 30555, 15911 => 26230,
    419     15912 => 40120, 15913 => 20140, 15914 => 24778, 15915 => 31934, 15916 => 31923,
    420     15917 => 32463, 15918 => 20117, 15919 => 35686, 15920 => 26223, 15921 => 39048,
    421     15922 => 38745, 15923 => 22659, 15924 => 25964, 15925 => 38236, 15926 => 24452,
    422     15927 => 30153, 15928 => 38742, 15929 => 31455, 15930 => 31454, 15931 => 20928,
    423     15932 => 28847, 15933 => 31384, 15934 => 25578, 15935 => 31350, 15936 => 32416,
    424     15937 => 29590, 15938 => 38893, 15939 => 20037, 15940 => 28792, 15941 => 20061,
    425     15942 => 37202, 15943 => 21417, 15944 => 25937, 15945 => 26087, 15946 => 33276,
    426     15947 => 33285, 15948 => 21646, 15949 => 23601, 15950 => 30106, 15951 => 38816,
    427     15952 => 25304, 15953 => 29401, 15954 => 30141, 15955 => 23621, 15956 => 39545,
    428     15957 => 33738, 15958 => 23616, 15959 => 21632, 15960 => 30697, 15961 => 20030,
    429     15962 => 27822, 15963 => 32858, 15964 => 25298, 15965 => 25454, 15966 => 24040,
    430     15967 => 20855, 15968 => 36317, 15969 => 36382, 15970 => 38191, 15971 => 20465,
    431     15972 => 21477, 15973 => 24807, 15974 => 28844, 15975 => 21095, 15976 => 25424,
    432     15977 => 40515, 15978 => 23071, 15979 => 20518, 15980 => 30519, 15981 => 21367,
    433     15982 => 32482, 15983 => 25733, 15984 => 25899, 15985 => 25225, 15986 => 25496,
    434     15987 => 20500, 15988 => 29237, 15989 => 35273, 15990 => 20915, 15991 => 35776,
    435     15992 => 32477, 15993 => 22343, 15994 => 33740, 15995 => 38055, 15996 => 20891,
    436     15997 => 21531, 15998 => 23803, 16161 => 20426, 16162 => 31459, 16163 => 27994,
    437     16164 => 37089, 16165 => 39567, 16166 => 21888, 16167 => 21654, 16168 => 21345,
    438     16169 => 21679, 16170 => 24320, 16171 => 25577, 16172 => 26999, 16173 => 20975,
    439     16174 => 24936, 16175 => 21002, 16176 => 22570, 16177 => 21208, 16178 => 22350,
    440     16179 => 30733, 16180 => 30475, 16181 => 24247, 16182 => 24951, 16183 => 31968,
    441     16184 => 25179, 16185 => 25239, 16186 => 20130, 16187 => 28821, 16188 => 32771,
    442     16189 => 25335, 16190 => 28900, 16191 => 38752, 16192 => 22391, 16193 => 33499,
    443     16194 => 26607, 16195 => 26869, 16196 => 30933, 16197 => 39063, 16198 => 31185,
    444     16199 => 22771, 16200 => 21683, 16201 => 21487, 16202 => 28212, 16203 => 20811,
    445     16204 => 21051, 16205 => 23458, 16206 => 35838, 16207 => 32943, 16208 => 21827,
    446     16209 => 22438, 16210 => 24691, 16211 => 22353, 16212 => 21549, 16213 => 31354,
    447     16214 => 24656, 16215 => 23380, 16216 => 25511, 16217 => 25248, 16218 => 21475,
    448     16219 => 25187, 16220 => 23495, 16221 => 26543, 16222 => 21741, 16223 => 31391,
    449     16224 => 33510, 16225 => 37239, 16226 => 24211, 16227 => 35044, 16228 => 22840,
    450     16229 => 22446, 16230 => 25358, 16231 => 36328, 16232 => 33007, 16233 => 22359,
    451     16234 => 31607, 16235 => 20393, 16236 => 24555, 16237 => 23485, 16238 => 27454,
    452     16239 => 21281, 16240 => 31568, 16241 => 29378, 16242 => 26694, 16243 => 30719,
    453     16244 => 30518, 16245 => 26103, 16246 => 20917, 16247 => 20111, 16248 => 30420,
    454     16249 => 23743, 16250 => 31397, 16251 => 33909, 16252 => 22862, 16253 => 39745,
    455     16254 => 20608, 16417 => 39304, 16418 => 24871, 16419 => 28291, 16420 => 22372,
    456     16421 => 26118, 16422 => 25414, 16423 => 22256, 16424 => 25324, 16425 => 25193,
    457     16426 => 24275, 16427 => 38420, 16428 => 22403, 16429 => 25289, 16430 => 21895,
    458     16431 => 34593, 16432 => 33098, 16433 => 36771, 16434 => 21862, 16435 => 33713,
    459     16436 => 26469, 16437 => 36182, 16438 => 34013, 16439 => 23146, 16440 => 26639,
    460     16441 => 25318, 16442 => 31726, 16443 => 38417, 16444 => 20848, 16445 => 28572,
    461     16446 => 35888, 16447 => 25597, 16448 => 35272, 16449 => 25042, 16450 => 32518,
    462     16451 => 28866, 16452 => 28389, 16453 => 29701, 16454 => 27028, 16455 => 29436,
    463     16456 => 24266, 16457 => 37070, 16458 => 26391, 16459 => 28010, 16460 => 25438,
    464     16461 => 21171, 16462 => 29282, 16463 => 32769, 16464 => 20332, 16465 => 23013,
    465     16466 => 37226, 16467 => 28889, 16468 => 28061, 16469 => 21202, 16470 => 20048,
    466     16471 => 38647, 16472 => 38253, 16473 => 34174, 16474 => 30922, 16475 => 32047,
    467     16476 => 20769, 16477 => 22418, 16478 => 25794, 16479 => 32907, 16480 => 31867,
    468     16481 => 27882, 16482 => 26865, 16483 => 26974, 16484 => 20919, 16485 => 21400,
    469     16486 => 26792, 16487 => 29313, 16488 => 40654, 16489 => 31729, 16490 => 29432,
    470     16491 => 31163, 16492 => 28435, 16493 => 29702, 16494 => 26446, 16495 => 37324,
    471     16496 => 40100, 16497 => 31036, 16498 => 33673, 16499 => 33620, 16500 => 21519,
    472     16501 => 26647, 16502 => 20029, 16503 => 21385, 16504 => 21169, 16505 => 30782,
    473     16506 => 21382, 16507 => 21033, 16508 => 20616, 16509 => 20363, 16510 => 20432,
    474     16673 => 30178, 16674 => 31435, 16675 => 31890, 16676 => 27813, 16677 => 38582,
    475     16678 => 21147, 16679 => 29827, 16680 => 21737, 16681 => 20457, 16682 => 32852,
    476     16683 => 33714, 16684 => 36830, 16685 => 38256, 16686 => 24265, 16687 => 24604,
    477     16688 => 28063, 16689 => 24088, 16690 => 25947, 16691 => 33080, 16692 => 38142,
    478     16693 => 24651, 16694 => 28860, 16695 => 32451, 16696 => 31918, 16697 => 20937,
    479     16698 => 26753, 16699 => 31921, 16700 => 33391, 16701 => 20004, 16702 => 36742,
    480     16703 => 37327, 16704 => 26238, 16705 => 20142, 16706 => 35845, 16707 => 25769,
    481     16708 => 32842, 16709 => 20698, 16710 => 30103, 16711 => 29134, 16712 => 23525,
    482     16713 => 36797, 16714 => 28518, 16715 => 20102, 16716 => 25730, 16717 => 38243,
    483     16718 => 24278, 16719 => 26009, 16720 => 21015, 16721 => 35010, 16722 => 28872,
    484     16723 => 21155, 16724 => 29454, 16725 => 29747, 16726 => 26519, 16727 => 30967,
    485     16728 => 38678, 16729 => 20020, 16730 => 37051, 16731 => 40158, 16732 => 28107,
    486     16733 => 20955, 16734 => 36161, 16735 => 21533, 16736 => 25294, 16737 => 29618,
    487     16738 => 33777, 16739 => 38646, 16740 => 40836, 16741 => 38083, 16742 => 20278,
    488     16743 => 32666, 16744 => 20940, 16745 => 28789, 16746 => 38517, 16747 => 23725,
    489     16748 => 39046, 16749 => 21478, 16750 => 20196, 16751 => 28316, 16752 => 29705,
    490     16753 => 27060, 16754 => 30827, 16755 => 39311, 16756 => 30041, 16757 => 21016,
    491     16758 => 30244, 16759 => 27969, 16760 => 26611, 16761 => 20845, 16762 => 40857,
    492     16763 => 32843, 16764 => 21657, 16765 => 31548, 16766 => 31423, 16929 => 38534,
    493     16930 => 22404, 16931 => 25314, 16932 => 38471, 16933 => 27004, 16934 => 23044,
    494     16935 => 25602, 16936 => 31699, 16937 => 28431, 16938 => 38475, 16939 => 33446,
    495     16940 => 21346, 16941 => 39045, 16942 => 24208, 16943 => 28809, 16944 => 25523,
    496     16945 => 21348, 16946 => 34383, 16947 => 40065, 16948 => 40595, 16949 => 30860,
    497     16950 => 38706, 16951 => 36335, 16952 => 36162, 16953 => 40575, 16954 => 28510,
    498     16955 => 31108, 16956 => 24405, 16957 => 38470, 16958 => 25134, 16959 => 39540,
    499     16960 => 21525, 16961 => 38109, 16962 => 20387, 16963 => 26053, 16964 => 23653,
    500     16965 => 23649, 16966 => 32533, 16967 => 34385, 16968 => 27695, 16969 => 24459,
    501     16970 => 29575, 16971 => 28388, 16972 => 32511, 16973 => 23782, 16974 => 25371,
    502     16975 => 23402, 16976 => 28390, 16977 => 21365, 16978 => 20081, 16979 => 25504,
    503     16980 => 30053, 16981 => 25249, 16982 => 36718, 16983 => 20262, 16984 => 20177,
    504     16985 => 27814, 16986 => 32438, 16987 => 35770, 16988 => 33821, 16989 => 34746,
    505     16990 => 32599, 16991 => 36923, 16992 => 38179, 16993 => 31657, 16994 => 39585,
    506     16995 => 35064, 16996 => 33853, 16997 => 27931, 16998 => 39558, 16999 => 32476,
    507     17000 => 22920, 17001 => 40635, 17002 => 29595, 17003 => 30721, 17004 => 34434,
    508     17005 => 39532, 17006 => 39554, 17007 => 22043, 17008 => 21527, 17009 => 22475,
    509     17010 => 20080, 17011 => 40614, 17012 => 21334, 17013 => 36808, 17014 => 33033,
    510     17015 => 30610, 17016 => 39314, 17017 => 34542, 17018 => 28385, 17019 => 34067,
    511     17020 => 26364, 17021 => 24930, 17022 => 28459, 17185 => 35881, 17186 => 33426,
    512     17187 => 33579, 17188 => 30450, 17189 => 27667, 17190 => 24537, 17191 => 33725,
    513     17192 => 29483, 17193 => 33541, 17194 => 38170, 17195 => 27611, 17196 => 30683,
    514     17197 => 38086, 17198 => 21359, 17199 => 33538, 17200 => 20882, 17201 => 24125,
    515     17202 => 35980, 17203 => 36152, 17204 => 20040, 17205 => 29611, 17206 => 26522,
    516     17207 => 26757, 17208 => 37238, 17209 => 38665, 17210 => 29028, 17211 => 27809,
    517     17212 => 30473, 17213 => 23186, 17214 => 38209, 17215 => 27599, 17216 => 32654,
    518     17217 => 26151, 17218 => 23504, 17219 => 22969, 17220 => 23194, 17221 => 38376,
    519     17222 => 38391, 17223 => 20204, 17224 => 33804, 17225 => 33945, 17226 => 27308,
    520     17227 => 30431, 17228 => 38192, 17229 => 29467, 17230 => 26790, 17231 => 23391,
    521     17232 => 30511, 17233 => 37274, 17234 => 38753, 17235 => 31964, 17236 => 36855,
    522     17237 => 35868, 17238 => 24357, 17239 => 31859, 17240 => 31192, 17241 => 35269,
    523     17242 => 27852, 17243 => 34588, 17244 => 23494, 17245 => 24130, 17246 => 26825,
    524     17247 => 30496, 17248 => 32501, 17249 => 20885, 17250 => 20813, 17251 => 21193,
    525     17252 => 23081, 17253 => 32517, 17254 => 38754, 17255 => 33495, 17256 => 25551,
    526     17257 => 30596, 17258 => 34256, 17259 => 31186, 17260 => 28218, 17261 => 24217,
    527     17262 => 22937, 17263 => 34065, 17264 => 28781, 17265 => 27665, 17266 => 25279,
    528     17267 => 30399, 17268 => 25935, 17269 => 24751, 17270 => 38397, 17271 => 26126,
    529     17272 => 34719, 17273 => 40483, 17274 => 38125, 17275 => 21517, 17276 => 21629,
    530     17277 => 35884, 17278 => 25720, 17441 => 25721, 17442 => 34321, 17443 => 27169,
    531     17444 => 33180, 17445 => 30952, 17446 => 25705, 17447 => 39764, 17448 => 25273,
    532     17449 => 26411, 17450 => 33707, 17451 => 22696, 17452 => 40664, 17453 => 27819,
    533     17454 => 28448, 17455 => 23518, 17456 => 38476, 17457 => 35851, 17458 => 29279,
    534     17459 => 26576, 17460 => 25287, 17461 => 29281, 17462 => 20137, 17463 => 22982,
    535     17464 => 27597, 17465 => 22675, 17466 => 26286, 17467 => 24149, 17468 => 21215,
    536     17469 => 24917, 17470 => 26408, 17471 => 30446, 17472 => 30566, 17473 => 29287,
    537     17474 => 31302, 17475 => 25343, 17476 => 21738, 17477 => 21584, 17478 => 38048,
    538     17479 => 37027, 17480 => 23068, 17481 => 32435, 17482 => 27670, 17483 => 20035,
    539     17484 => 22902, 17485 => 32784, 17486 => 22856, 17487 => 21335, 17488 => 30007,
    540     17489 => 38590, 17490 => 22218, 17491 => 25376, 17492 => 33041, 17493 => 24700,
    541     17494 => 38393, 17495 => 28118, 17496 => 21602, 17497 => 39297, 17498 => 20869,
    542     17499 => 23273, 17500 => 33021, 17501 => 22958, 17502 => 38675, 17503 => 20522,
    543     17504 => 27877, 17505 => 23612, 17506 => 25311, 17507 => 20320, 17508 => 21311,
    544     17509 => 33147, 17510 => 36870, 17511 => 28346, 17512 => 34091, 17513 => 25288,
    545     17514 => 24180, 17515 => 30910, 17516 => 25781, 17517 => 25467, 17518 => 24565,
    546     17519 => 23064, 17520 => 37247, 17521 => 40479, 17522 => 23615, 17523 => 25423,
    547     17524 => 32834, 17525 => 23421, 17526 => 21870, 17527 => 38218, 17528 => 38221,
    548     17529 => 28037, 17530 => 24744, 17531 => 26592, 17532 => 29406, 17533 => 20957,
    549     17534 => 23425, 17697 => 25319, 17698 => 27870, 17699 => 29275, 17700 => 25197,
    550     17701 => 38062, 17702 => 32445, 17703 => 33043, 17704 => 27987, 17705 => 20892,
    551     17706 => 24324, 17707 => 22900, 17708 => 21162, 17709 => 24594, 17710 => 22899,
    552     17711 => 26262, 17712 => 34384, 17713 => 30111, 17714 => 25386, 17715 => 25062,
    553     17716 => 31983, 17717 => 35834, 17718 => 21734, 17719 => 27431, 17720 => 40485,
    554     17721 => 27572, 17722 => 34261, 17723 => 21589, 17724 => 20598, 17725 => 27812,
    555     17726 => 21866, 17727 => 36276, 17728 => 29228, 17729 => 24085, 17730 => 24597,
    556     17731 => 29750, 17732 => 25293, 17733 => 25490, 17734 => 29260, 17735 => 24472,
    557     17736 => 28227, 17737 => 27966, 17738 => 25856, 17739 => 28504, 17740 => 30424,
    558     17741 => 30928, 17742 => 30460, 17743 => 30036, 17744 => 21028, 17745 => 21467,
    559     17746 => 20051, 17747 => 24222, 17748 => 26049, 17749 => 32810, 17750 => 32982,
    560     17751 => 25243, 17752 => 21638, 17753 => 21032, 17754 => 28846, 17755 => 34957,
    561     17756 => 36305, 17757 => 27873, 17758 => 21624, 17759 => 32986, 17760 => 22521,
    562     17761 => 35060, 17762 => 36180, 17763 => 38506, 17764 => 37197, 17765 => 20329,
    563     17766 => 27803, 17767 => 21943, 17768 => 30406, 17769 => 30768, 17770 => 25256,
    564     17771 => 28921, 17772 => 28558, 17773 => 24429, 17774 => 34028, 17775 => 26842,
    565     17776 => 30844, 17777 => 31735, 17778 => 33192, 17779 => 26379, 17780 => 40527,
    566     17781 => 25447, 17782 => 30896, 17783 => 22383, 17784 => 30738, 17785 => 38713,
    567     17786 => 25209, 17787 => 25259, 17788 => 21128, 17789 => 29749, 17790 => 27607,
    568     17953 => 21860, 17954 => 33086, 17955 => 30130, 17956 => 30382, 17957 => 21305,
    569     17958 => 30174, 17959 => 20731, 17960 => 23617, 17961 => 35692, 17962 => 31687,
    570     17963 => 20559, 17964 => 29255, 17965 => 39575, 17966 => 39128, 17967 => 28418,
    571     17968 => 29922, 17969 => 31080, 17970 => 25735, 17971 => 30629, 17972 => 25340,
    572     17973 => 39057, 17974 => 36139, 17975 => 21697, 17976 => 32856, 17977 => 20050,
    573     17978 => 22378, 17979 => 33529, 17980 => 33805, 17981 => 24179, 17982 => 20973,
    574     17983 => 29942, 17984 => 35780, 17985 => 23631, 17986 => 22369, 17987 => 27900,
    575     17988 => 39047, 17989 => 23110, 17990 => 30772, 17991 => 39748, 17992 => 36843,
    576     17993 => 31893, 17994 => 21078, 17995 => 25169, 17996 => 38138, 17997 => 20166,
    577     17998 => 33670, 17999 => 33889, 18000 => 33769, 18001 => 33970, 18002 => 22484,
    578     18003 => 26420, 18004 => 22275, 18005 => 26222, 18006 => 28006, 18007 => 35889,
    579     18008 => 26333, 18009 => 28689, 18010 => 26399, 18011 => 27450, 18012 => 26646,
    580     18013 => 25114, 18014 => 22971, 18015 => 19971, 18016 => 20932, 18017 => 28422,
    581     18018 => 26578, 18019 => 27791, 18020 => 20854, 18021 => 26827, 18022 => 22855,
    582     18023 => 27495, 18024 => 30054, 18025 => 23822, 18026 => 33040, 18027 => 40784,
    583     18028 => 26071, 18029 => 31048, 18030 => 31041, 18031 => 39569, 18032 => 36215,
    584     18033 => 23682, 18034 => 20062, 18035 => 20225, 18036 => 21551, 18037 => 22865,
    585     18038 => 30732, 18039 => 22120, 18040 => 27668, 18041 => 36804, 18042 => 24323,
    586     18043 => 27773, 18044 => 27875, 18045 => 35755, 18046 => 25488, 18209 => 24688,
    587     18210 => 27965, 18211 => 29301, 18212 => 25190, 18213 => 38030, 18214 => 38085,
    588     18215 => 21315, 18216 => 36801, 18217 => 31614, 18218 => 20191, 18219 => 35878,
    589     18220 => 20094, 18221 => 40660, 18222 => 38065, 18223 => 38067, 18224 => 21069,
    590     18225 => 28508, 18226 => 36963, 18227 => 27973, 18228 => 35892, 18229 => 22545,
    591     18230 => 23884, 18231 => 27424, 18232 => 27465, 18233 => 26538, 18234 => 21595,
    592     18235 => 33108, 18236 => 32652, 18237 => 22681, 18238 => 34103, 18239 => 24378,
    593     18240 => 25250, 18241 => 27207, 18242 => 38201, 18243 => 25970, 18244 => 24708,
    594     18245 => 26725, 18246 => 30631, 18247 => 20052, 18248 => 20392, 18249 => 24039,
    595     18250 => 38808, 18251 => 25772, 18252 => 32728, 18253 => 23789, 18254 => 20431,
    596     18255 => 31373, 18256 => 20999, 18257 => 33540, 18258 => 19988, 18259 => 24623,
    597     18260 => 31363, 18261 => 38054, 18262 => 20405, 18263 => 20146, 18264 => 31206,
    598     18265 => 29748, 18266 => 21220, 18267 => 33465, 18268 => 25810, 18269 => 31165,
    599     18270 => 23517, 18271 => 27777, 18272 => 38738, 18273 => 36731, 18274 => 27682,
    600     18275 => 20542, 18276 => 21375, 18277 => 28165, 18278 => 25806, 18279 => 26228,
    601     18280 => 27696, 18281 => 24773, 18282 => 39031, 18283 => 35831, 18284 => 24198,
    602     18285 => 29756, 18286 => 31351, 18287 => 31179, 18288 => 19992, 18289 => 37041,
    603     18290 => 29699, 18291 => 27714, 18292 => 22234, 18293 => 37195, 18294 => 27845,
    604     18295 => 36235, 18296 => 21306, 18297 => 34502, 18298 => 26354, 18299 => 36527,
    605     18300 => 23624, 18301 => 39537, 18302 => 28192, 18465 => 21462, 18466 => 23094,
    606     18467 => 40843, 18468 => 36259, 18469 => 21435, 18470 => 22280, 18471 => 39079,
    607     18472 => 26435, 18473 => 37275, 18474 => 27849, 18475 => 20840, 18476 => 30154,
    608     18477 => 25331, 18478 => 29356, 18479 => 21048, 18480 => 21149, 18481 => 32570,
    609     18482 => 28820, 18483 => 30264, 18484 => 21364, 18485 => 40522, 18486 => 27063,
    610     18487 => 30830, 18488 => 38592, 18489 => 35033, 18490 => 32676, 18491 => 28982,
    611     18492 => 29123, 18493 => 20873, 18494 => 26579, 18495 => 29924, 18496 => 22756,
    612     18497 => 25880, 18498 => 22199, 18499 => 35753, 18500 => 39286, 18501 => 25200,
    613     18502 => 32469, 18503 => 24825, 18504 => 28909, 18505 => 22764, 18506 => 20161,
    614     18507 => 20154, 18508 => 24525, 18509 => 38887, 18510 => 20219, 18511 => 35748,
    615     18512 => 20995, 18513 => 22922, 18514 => 32427, 18515 => 25172, 18516 => 20173,
    616     18517 => 26085, 18518 => 25102, 18519 => 33592, 18520 => 33993, 18521 => 33635,
    617     18522 => 34701, 18523 => 29076, 18524 => 28342, 18525 => 23481, 18526 => 32466,
    618     18527 => 20887, 18528 => 25545, 18529 => 26580, 18530 => 32905, 18531 => 33593,
    619     18532 => 34837, 18533 => 20754, 18534 => 23418, 18535 => 22914, 18536 => 36785,
    620     18537 => 20083, 18538 => 27741, 18539 => 20837, 18540 => 35109, 18541 => 36719,
    621     18542 => 38446, 18543 => 34122, 18544 => 29790, 18545 => 38160, 18546 => 38384,
    622     18547 => 28070, 18548 => 33509, 18549 => 24369, 18550 => 25746, 18551 => 27922,
    623     18552 => 33832, 18553 => 33134, 18554 => 40131, 18555 => 22622, 18556 => 36187,
    624     18557 => 19977, 18558 => 21441, 18721 => 20254, 18722 => 25955, 18723 => 26705,
    625     18724 => 21971, 18725 => 20007, 18726 => 25620, 18727 => 39578, 18728 => 25195,
    626     18729 => 23234, 18730 => 29791, 18731 => 33394, 18732 => 28073, 18733 => 26862,
    627     18734 => 20711, 18735 => 33678, 18736 => 30722, 18737 => 26432, 18738 => 21049,
    628     18739 => 27801, 18740 => 32433, 18741 => 20667, 18742 => 21861, 18743 => 29022,
    629     18744 => 31579, 18745 => 26194, 18746 => 29642, 18747 => 33515, 18748 => 26441,
    630     18749 => 23665, 18750 => 21024, 18751 => 29053, 18752 => 34923, 18753 => 38378,
    631     18754 => 38485, 18755 => 25797, 18756 => 36193, 18757 => 33203, 18758 => 21892,
    632     18759 => 27733, 18760 => 25159, 18761 => 32558, 18762 => 22674, 18763 => 20260,
    633     18764 => 21830, 18765 => 36175, 18766 => 26188, 18767 => 19978, 18768 => 23578,
    634     18769 => 35059, 18770 => 26786, 18771 => 25422, 18772 => 31245, 18773 => 28903,
    635     18774 => 33421, 18775 => 21242, 18776 => 38902, 18777 => 23569, 18778 => 21736,
    636     18779 => 37045, 18780 => 32461, 18781 => 22882, 18782 => 36170, 18783 => 34503,
    637     18784 => 33292, 18785 => 33293, 18786 => 36198, 18787 => 25668, 18788 => 23556,
    638     18789 => 24913, 18790 => 28041, 18791 => 31038, 18792 => 35774, 18793 => 30775,
    639     18794 => 30003, 18795 => 21627, 18796 => 20280, 18797 => 36523, 18798 => 28145,
    640     18799 => 23072, 18800 => 32453, 18801 => 31070, 18802 => 27784, 18803 => 23457,
    641     18804 => 23158, 18805 => 29978, 18806 => 32958, 18807 => 24910, 18808 => 28183,
    642     18809 => 22768, 18810 => 29983, 18811 => 29989, 18812 => 29298, 18813 => 21319,
    643     18814 => 32499, 18977 => 30465, 18978 => 30427, 18979 => 21097, 18980 => 32988,
    644     18981 => 22307, 18982 => 24072, 18983 => 22833, 18984 => 29422, 18985 => 26045,
    645     18986 => 28287, 18987 => 35799, 18988 => 23608, 18989 => 34417, 18990 => 21313,
    646     18991 => 30707, 18992 => 25342, 18993 => 26102, 18994 => 20160, 18995 => 39135,
    647     18996 => 34432, 18997 => 23454, 18998 => 35782, 18999 => 21490, 19000 => 30690,
    648     19001 => 20351, 19002 => 23630, 19003 => 39542, 19004 => 22987, 19005 => 24335,
    649     19006 => 31034, 19007 => 22763, 19008 => 19990, 19009 => 26623, 19010 => 20107,
    650     19011 => 25325, 19012 => 35475, 19013 => 36893, 19014 => 21183, 19015 => 26159,
    651     19016 => 21980, 19017 => 22124, 19018 => 36866, 19019 => 20181, 19020 => 20365,
    652     19021 => 37322, 19022 => 39280, 19023 => 27663, 19024 => 24066, 19025 => 24643,
    653     19026 => 23460, 19027 => 35270, 19028 => 35797, 19029 => 25910, 19030 => 25163,
    654     19031 => 39318, 19032 => 23432, 19033 => 23551, 19034 => 25480, 19035 => 21806,
    655     19036 => 21463, 19037 => 30246, 19038 => 20861, 19039 => 34092, 19040 => 26530,
    656     19041 => 26803, 19042 => 27530, 19043 => 25234, 19044 => 36755, 19045 => 21460,
    657     19046 => 33298, 19047 => 28113, 19048 => 30095, 19049 => 20070, 19050 => 36174,
    658     19051 => 23408, 19052 => 29087, 19053 => 34223, 19054 => 26257, 19055 => 26329,
    659     19056 => 32626, 19057 => 34560, 19058 => 40653, 19059 => 40736, 19060 => 23646,
    660     19061 => 26415, 19062 => 36848, 19063 => 26641, 19064 => 26463, 19065 => 25101,
    661     19066 => 31446, 19067 => 22661, 19068 => 24246, 19069 => 25968, 19070 => 28465,
    662     19233 => 24661, 19234 => 21047, 19235 => 32781, 19236 => 25684, 19237 => 34928,
    663     19238 => 29993, 19239 => 24069, 19240 => 26643, 19241 => 25332, 19242 => 38684,
    664     19243 => 21452, 19244 => 29245, 19245 => 35841, 19246 => 27700, 19247 => 30561,
    665     19248 => 31246, 19249 => 21550, 19250 => 30636, 19251 => 39034, 19252 => 33308,
    666     19253 => 35828, 19254 => 30805, 19255 => 26388, 19256 => 28865, 19257 => 26031,
    667     19258 => 25749, 19259 => 22070, 19260 => 24605, 19261 => 31169, 19262 => 21496,
    668     19263 => 19997, 19264 => 27515, 19265 => 32902, 19266 => 23546, 19267 => 21987,
    669     19268 => 22235, 19269 => 20282, 19270 => 20284, 19271 => 39282, 19272 => 24051,
    670     19273 => 26494, 19274 => 32824, 19275 => 24578, 19276 => 39042, 19277 => 36865,
    671     19278 => 23435, 19279 => 35772, 19280 => 35829, 19281 => 25628, 19282 => 33368,
    672     19283 => 25822, 19284 => 22013, 19285 => 33487, 19286 => 37221, 19287 => 20439,
    673     19288 => 32032, 19289 => 36895, 19290 => 31903, 19291 => 20723, 19292 => 22609,
    674     19293 => 28335, 19294 => 23487, 19295 => 35785, 19296 => 32899, 19297 => 37240,
    675     19298 => 33948, 19299 => 31639, 19300 => 34429, 19301 => 38539, 19302 => 38543,
    676     19303 => 32485, 19304 => 39635, 19305 => 30862, 19306 => 23681, 19307 => 31319,
    677     19308 => 36930, 19309 => 38567, 19310 => 31071, 19311 => 23385, 19312 => 25439,
    678     19313 => 31499, 19314 => 34001, 19315 => 26797, 19316 => 21766, 19317 => 32553,
    679     19318 => 29712, 19319 => 32034, 19320 => 38145, 19321 => 25152, 19322 => 22604,
    680     19323 => 20182, 19324 => 23427, 19325 => 22905, 19326 => 22612, 19489 => 29549,
    681     19490 => 25374, 19491 => 36427, 19492 => 36367, 19493 => 32974, 19494 => 33492,
    682     19495 => 25260, 19496 => 21488, 19497 => 27888, 19498 => 37214, 19499 => 22826,
    683     19500 => 24577, 19501 => 27760, 19502 => 22349, 19503 => 25674, 19504 => 36138,
    684     19505 => 30251, 19506 => 28393, 19507 => 22363, 19508 => 27264, 19509 => 30192,
    685     19510 => 28525, 19511 => 35885, 19512 => 35848, 19513 => 22374, 19514 => 27631,
    686     19515 => 34962, 19516 => 30899, 19517 => 25506, 19518 => 21497, 19519 => 28845,
    687     19520 => 27748, 19521 => 22616, 19522 => 25642, 19523 => 22530, 19524 => 26848,
    688     19525 => 33179, 19526 => 21776, 19527 => 31958, 19528 => 20504, 19529 => 36538,
    689     19530 => 28108, 19531 => 36255, 19532 => 28907, 19533 => 25487, 19534 => 28059,
    690     19535 => 28372, 19536 => 32486, 19537 => 33796, 19538 => 26691, 19539 => 36867,
    691     19540 => 28120, 19541 => 38518, 19542 => 35752, 19543 => 22871, 19544 => 29305,
    692     19545 => 34276, 19546 => 33150, 19547 => 30140, 19548 => 35466, 19549 => 26799,
    693     19550 => 21076, 19551 => 36386, 19552 => 38161, 19553 => 25552, 19554 => 39064,
    694     19555 => 36420, 19556 => 21884, 19557 => 20307, 19558 => 26367, 19559 => 22159,
    695     19560 => 24789, 19561 => 28053, 19562 => 21059, 19563 => 23625, 19564 => 22825,
    696     19565 => 28155, 19566 => 22635, 19567 => 30000, 19568 => 29980, 19569 => 24684,
    697     19570 => 33300, 19571 => 33094, 19572 => 25361, 19573 => 26465, 19574 => 36834,
    698     19575 => 30522, 19576 => 36339, 19577 => 36148, 19578 => 38081, 19579 => 24086,
    699     19580 => 21381, 19581 => 21548, 19582 => 28867, 19745 => 27712, 19746 => 24311,
    700     19747 => 20572, 19748 => 20141, 19749 => 24237, 19750 => 25402, 19751 => 33351,
    701     19752 => 36890, 19753 => 26704, 19754 => 37230, 19755 => 30643, 19756 => 21516,
    702     19757 => 38108, 19758 => 24420, 19759 => 31461, 19760 => 26742, 19761 => 25413,
    703     19762 => 31570, 19763 => 32479, 19764 => 30171, 19765 => 20599, 19766 => 25237,
    704     19767 => 22836, 19768 => 36879, 19769 => 20984, 19770 => 31171, 19771 => 31361,
    705     19772 => 22270, 19773 => 24466, 19774 => 36884, 19775 => 28034, 19776 => 23648,
    706     19777 => 22303, 19778 => 21520, 19779 => 20820, 19780 => 28237, 19781 => 22242,
    707     19782 => 25512, 19783 => 39059, 19784 => 33151, 19785 => 34581, 19786 => 35114,
    708     19787 => 36864, 19788 => 21534, 19789 => 23663, 19790 => 33216, 19791 => 25302,
    709     19792 => 25176, 19793 => 33073, 19794 => 40501, 19795 => 38464, 19796 => 39534,
    710     19797 => 39548, 19798 => 26925, 19799 => 22949, 19800 => 25299, 19801 => 21822,
    711     19802 => 25366, 19803 => 21703, 19804 => 34521, 19805 => 27964, 19806 => 23043,
    712     19807 => 29926, 19808 => 34972, 19809 => 27498, 19810 => 22806, 19811 => 35916,
    713     19812 => 24367, 19813 => 28286, 19814 => 29609, 19815 => 39037, 19816 => 20024,
    714     19817 => 28919, 19818 => 23436, 19819 => 30871, 19820 => 25405, 19821 => 26202,
    715     19822 => 30358, 19823 => 24779, 19824 => 23451, 19825 => 23113, 19826 => 19975,
    716     19827 => 33109, 19828 => 27754, 19829 => 29579, 19830 => 20129, 19831 => 26505,
    717     19832 => 32593, 19833 => 24448, 19834 => 26106, 19835 => 26395, 19836 => 24536,
    718     19837 => 22916, 19838 => 23041, 20001 => 24013, 20002 => 24494, 20003 => 21361,
    719     20004 => 38886, 20005 => 36829, 20006 => 26693, 20007 => 22260, 20008 => 21807,
    720     20009 => 24799, 20010 => 20026, 20011 => 28493, 20012 => 32500, 20013 => 33479,
    721     20014 => 33806, 20015 => 22996, 20016 => 20255, 20017 => 20266, 20018 => 23614,
    722     20019 => 32428, 20020 => 26410, 20021 => 34074, 20022 => 21619, 20023 => 30031,
    723     20024 => 32963, 20025 => 21890, 20026 => 39759, 20027 => 20301, 20028 => 28205,
    724     20029 => 35859, 20030 => 23561, 20031 => 24944, 20032 => 21355, 20033 => 30239,
    725     20034 => 28201, 20035 => 34442, 20036 => 25991, 20037 => 38395, 20038 => 32441,
    726     20039 => 21563, 20040 => 31283, 20041 => 32010, 20042 => 38382, 20043 => 21985,
    727     20044 => 32705, 20045 => 29934, 20046 => 25373, 20047 => 34583, 20048 => 28065,
    728     20049 => 31389, 20050 => 25105, 20051 => 26017, 20052 => 21351, 20053 => 25569,
    729     20054 => 27779, 20055 => 24043, 20056 => 21596, 20057 => 38056, 20058 => 20044,
    730     20059 => 27745, 20060 => 35820, 20061 => 23627, 20062 => 26080, 20063 => 33436,
    731     20064 => 26791, 20065 => 21566, 20066 => 21556, 20067 => 27595, 20068 => 27494,
    732     20069 => 20116, 20070 => 25410, 20071 => 21320, 20072 => 33310, 20073 => 20237,
    733     20074 => 20398, 20075 => 22366, 20076 => 25098, 20077 => 38654, 20078 => 26212,
    734     20079 => 29289, 20080 => 21247, 20081 => 21153, 20082 => 24735, 20083 => 35823,
    735     20084 => 26132, 20085 => 29081, 20086 => 26512, 20087 => 35199, 20088 => 30802,
    736     20089 => 30717, 20090 => 26224, 20091 => 22075, 20092 => 21560, 20093 => 38177,
    737     20094 => 29306, 20257 => 31232, 20258 => 24687, 20259 => 24076, 20260 => 24713,
    738     20261 => 33181, 20262 => 22805, 20263 => 24796, 20264 => 29060, 20265 => 28911,
    739     20266 => 28330, 20267 => 27728, 20268 => 29312, 20269 => 27268, 20270 => 34989,
    740     20271 => 24109, 20272 => 20064, 20273 => 23219, 20274 => 21916, 20275 => 38115,
    741     20276 => 27927, 20277 => 31995, 20278 => 38553, 20279 => 25103, 20280 => 32454,
    742     20281 => 30606, 20282 => 34430, 20283 => 21283, 20284 => 38686, 20285 => 36758,
    743     20286 => 26247, 20287 => 23777, 20288 => 20384, 20289 => 29421, 20290 => 19979,
    744     20291 => 21414, 20292 => 22799, 20293 => 21523, 20294 => 25472, 20295 => 38184,
    745     20296 => 20808, 20297 => 20185, 20298 => 40092, 20299 => 32420, 20300 => 21688,
    746     20301 => 36132, 20302 => 34900, 20303 => 33335, 20304 => 38386, 20305 => 28046,
    747     20306 => 24358, 20307 => 23244, 20308 => 26174, 20309 => 38505, 20310 => 29616,
    748     20311 => 29486, 20312 => 21439, 20313 => 33146, 20314 => 39301, 20315 => 32673,
    749     20316 => 23466, 20317 => 38519, 20318 => 38480, 20319 => 32447, 20320 => 30456,
    750     20321 => 21410, 20322 => 38262, 20323 => 39321, 20324 => 31665, 20325 => 35140,
    751     20326 => 28248, 20327 => 20065, 20328 => 32724, 20329 => 31077, 20330 => 35814,
    752     20331 => 24819, 20332 => 21709, 20333 => 20139, 20334 => 39033, 20335 => 24055,
    753     20336 => 27233, 20337 => 20687, 20338 => 21521, 20339 => 35937, 20340 => 33831,
    754     20341 => 30813, 20342 => 38660, 20343 => 21066, 20344 => 21742, 20345 => 22179,
    755     20346 => 38144, 20347 => 28040, 20348 => 23477, 20349 => 28102, 20350 => 26195,
    756     20513 => 23567, 20514 => 23389, 20515 => 26657, 20516 => 32918, 20517 => 21880,
    757     20518 => 31505, 20519 => 25928, 20520 => 26964, 20521 => 20123, 20522 => 27463,
    758     20523 => 34638, 20524 => 38795, 20525 => 21327, 20526 => 25375, 20527 => 25658,
    759     20528 => 37034, 20529 => 26012, 20530 => 32961, 20531 => 35856, 20532 => 20889,
    760     20533 => 26800, 20534 => 21368, 20535 => 34809, 20536 => 25032, 20537 => 27844,
    761     20538 => 27899, 20539 => 35874, 20540 => 23633, 20541 => 34218, 20542 => 33455,
    762     20543 => 38156, 20544 => 27427, 20545 => 36763, 20546 => 26032, 20547 => 24571,
    763     20548 => 24515, 20549 => 20449, 20550 => 34885, 20551 => 26143, 20552 => 33125,
    764     20553 => 29481, 20554 => 24826, 20555 => 20852, 20556 => 21009, 20557 => 22411,
    765     20558 => 24418, 20559 => 37026, 20560 => 34892, 20561 => 37266, 20562 => 24184,
    766     20563 => 26447, 20564 => 24615, 20565 => 22995, 20566 => 20804, 20567 => 20982,
    767     20568 => 33016, 20569 => 21256, 20570 => 27769, 20571 => 38596, 20572 => 29066,
    768     20573 => 20241, 20574 => 20462, 20575 => 32670, 20576 => 26429, 20577 => 21957,
    769     20578 => 38152, 20579 => 31168, 20580 => 34966, 20581 => 32483, 20582 => 22687,
    770     20583 => 25100, 20584 => 38656, 20585 => 34394, 20586 => 22040, 20587 => 39035,
    771     20588 => 24464, 20589 => 35768, 20590 => 33988, 20591 => 37207, 20592 => 21465,
    772     20593 => 26093, 20594 => 24207, 20595 => 30044, 20596 => 24676, 20597 => 32110,
    773     20598 => 23167, 20599 => 32490, 20600 => 32493, 20601 => 36713, 20602 => 21927,
    774     20603 => 23459, 20604 => 24748, 20605 => 26059, 20606 => 29572, 20769 => 36873,
    775     20770 => 30307, 20771 => 30505, 20772 => 32474, 20773 => 38772, 20774 => 34203,
    776     20775 => 23398, 20776 => 31348, 20777 => 38634, 20778 => 34880, 20779 => 21195,
    777     20780 => 29071, 20781 => 24490, 20782 => 26092, 20783 => 35810, 20784 => 23547,
    778     20785 => 39535, 20786 => 24033, 20787 => 27529, 20788 => 27739, 20789 => 35757,
    779     20790 => 35759, 20791 => 36874, 20792 => 36805, 20793 => 21387, 20794 => 25276,
    780     20795 => 40486, 20796 => 40493, 20797 => 21568, 20798 => 20011, 20799 => 33469,
    781     20800 => 29273, 20801 => 34460, 20802 => 23830, 20803 => 34905, 20804 => 28079,
    782     20805 => 38597, 20806 => 21713, 20807 => 20122, 20808 => 35766, 20809 => 28937,
    783     20810 => 21693, 20811 => 38409, 20812 => 28895, 20813 => 28153, 20814 => 30416,
    784     20815 => 20005, 20816 => 30740, 20817 => 34578, 20818 => 23721, 20819 => 24310,
    785     20820 => 35328, 20821 => 39068, 20822 => 38414, 20823 => 28814, 20824 => 27839,
    786     20825 => 22852, 20826 => 25513, 20827 => 30524, 20828 => 34893, 20829 => 28436,
    787     20830 => 33395, 20831 => 22576, 20832 => 29141, 20833 => 21388, 20834 => 30746,
    788     20835 => 38593, 20836 => 21761, 20837 => 24422, 20838 => 28976, 20839 => 23476,
    789     20840 => 35866, 20841 => 39564, 20842 => 27523, 20843 => 22830, 20844 => 40495,
    790     20845 => 31207, 20846 => 26472, 20847 => 25196, 20848 => 20335, 20849 => 30113,
    791     20850 => 32650, 20851 => 27915, 20852 => 38451, 20853 => 27687, 20854 => 20208,
    792     20855 => 30162, 20856 => 20859, 20857 => 26679, 20858 => 28478, 20859 => 36992,
    793     20860 => 33136, 20861 => 22934, 20862 => 29814, 21025 => 25671, 21026 => 23591,
    794     21027 => 36965, 21028 => 31377, 21029 => 35875, 21030 => 23002, 21031 => 21676,
    795     21032 => 33280, 21033 => 33647, 21034 => 35201, 21035 => 32768, 21036 => 26928,
    796     21037 => 22094, 21038 => 32822, 21039 => 29239, 21040 => 37326, 21041 => 20918,
    797     21042 => 20063, 21043 => 39029, 21044 => 25494, 21045 => 19994, 21046 => 21494,
    798     21047 => 26355, 21048 => 33099, 21049 => 22812, 21050 => 28082, 21051 => 19968,
    799     21052 => 22777, 21053 => 21307, 21054 => 25558, 21055 => 38129, 21056 => 20381,
    800     21057 => 20234, 21058 => 34915, 21059 => 39056, 21060 => 22839, 21061 => 36951,
    801     21062 => 31227, 21063 => 20202, 21064 => 33008, 21065 => 30097, 21066 => 27778,
    802     21067 => 23452, 21068 => 23016, 21069 => 24413, 21070 => 26885, 21071 => 34433,
    803     21072 => 20506, 21073 => 24050, 21074 => 20057, 21075 => 30691, 21076 => 20197,
    804     21077 => 33402, 21078 => 25233, 21079 => 26131, 21080 => 37009, 21081 => 23673,
    805     21082 => 20159, 21083 => 24441, 21084 => 33222, 21085 => 36920, 21086 => 32900,
    806     21087 => 30123, 21088 => 20134, 21089 => 35028, 21090 => 24847, 21091 => 27589,
    807     21092 => 24518, 21093 => 20041, 21094 => 30410, 21095 => 28322, 21096 => 35811,
    808     21097 => 35758, 21098 => 35850, 21099 => 35793, 21100 => 24322, 21101 => 32764,
    809     21102 => 32716, 21103 => 32462, 21104 => 33589, 21105 => 33643, 21106 => 22240,
    810     21107 => 27575, 21108 => 38899, 21109 => 38452, 21110 => 23035, 21111 => 21535,
    811     21112 => 38134, 21113 => 28139, 21114 => 23493, 21115 => 39278, 21116 => 23609,
    812     21117 => 24341, 21118 => 38544, 21281 => 21360, 21282 => 33521, 21283 => 27185,
    813     21284 => 23156, 21285 => 40560, 21286 => 24212, 21287 => 32552, 21288 => 33721,
    814     21289 => 33828, 21290 => 33829, 21291 => 33639, 21292 => 34631, 21293 => 36814,
    815     21294 => 36194, 21295 => 30408, 21296 => 24433, 21297 => 39062, 21298 => 30828,
    816     21299 => 26144, 21300 => 21727, 21301 => 25317, 21302 => 20323, 21303 => 33219,
    817     21304 => 30152, 21305 => 24248, 21306 => 38605, 21307 => 36362, 21308 => 34553,
    818     21309 => 21647, 21310 => 27891, 21311 => 28044, 21312 => 27704, 21313 => 24703,
    819     21314 => 21191, 21315 => 29992, 21316 => 24189, 21317 => 20248, 21318 => 24736,
    820     21319 => 24551, 21320 => 23588, 21321 => 30001, 21322 => 37038, 21323 => 38080,
    821     21324 => 29369, 21325 => 27833, 21326 => 28216, 21327 => 37193, 21328 => 26377,
    822     21329 => 21451, 21330 => 21491, 21331 => 20305, 21332 => 37321, 21333 => 35825,
    823     21334 => 21448, 21335 => 24188, 21336 => 36802, 21337 => 28132, 21338 => 20110,
    824     21339 => 30402, 21340 => 27014, 21341 => 34398, 21342 => 24858, 21343 => 33286,
    825     21344 => 20313, 21345 => 20446, 21346 => 36926, 21347 => 40060, 21348 => 24841,
    826     21349 => 28189, 21350 => 28180, 21351 => 38533, 21352 => 20104, 21353 => 23089,
    827     21354 => 38632, 21355 => 19982, 21356 => 23679, 21357 => 31161, 21358 => 23431,
    828     21359 => 35821, 21360 => 32701, 21361 => 29577, 21362 => 22495, 21363 => 33419,
    829     21364 => 37057, 21365 => 21505, 21366 => 36935, 21367 => 21947, 21368 => 23786,
    830     21369 => 24481, 21370 => 24840, 21371 => 27442, 21372 => 29425, 21373 => 32946,
    831     21374 => 35465, 21537 => 28020, 21538 => 23507, 21539 => 35029, 21540 => 39044,
    832     21541 => 35947, 21542 => 39533, 21543 => 40499, 21544 => 28170, 21545 => 20900,
    833     21546 => 20803, 21547 => 22435, 21548 => 34945, 21549 => 21407, 21550 => 25588,
    834     21551 => 36757, 21552 => 22253, 21553 => 21592, 21554 => 22278, 21555 => 29503,
    835     21556 => 28304, 21557 => 32536, 21558 => 36828, 21559 => 33489, 21560 => 24895,
    836     21561 => 24616, 21562 => 38498, 21563 => 26352, 21564 => 32422, 21565 => 36234,
    837     21566 => 36291, 21567 => 38053, 21568 => 23731, 21569 => 31908, 21570 => 26376,
    838     21571 => 24742, 21572 => 38405, 21573 => 32792, 21574 => 20113, 21575 => 37095,
    839     21576 => 21248, 21577 => 38504, 21578 => 20801, 21579 => 36816, 21580 => 34164,
    840     21581 => 37213, 21582 => 26197, 21583 => 38901, 21584 => 23381, 21585 => 21277,
    841     21586 => 30776, 21587 => 26434, 21588 => 26685, 21589 => 21705, 21590 => 28798,
    842     21591 => 23472, 21592 => 36733, 21593 => 20877, 21594 => 22312, 21595 => 21681,
    843     21596 => 25874, 21597 => 26242, 21598 => 36190, 21599 => 36163, 21600 => 33039,
    844     21601 => 33900, 21602 => 36973, 21603 => 31967, 21604 => 20991, 21605 => 34299,
    845     21606 => 26531, 21607 => 26089, 21608 => 28577, 21609 => 34468, 21610 => 36481,
    846     21611 => 22122, 21612 => 36896, 21613 => 30338, 21614 => 28790, 21615 => 29157,
    847     21616 => 36131, 21617 => 25321, 21618 => 21017, 21619 => 27901, 21620 => 36156,
    848     21621 => 24590, 21622 => 22686, 21623 => 24974, 21624 => 26366, 21625 => 36192,
    849     21626 => 25166, 21627 => 21939, 21628 => 28195, 21629 => 26413, 21630 => 36711,
    850     21793 => 38113, 21794 => 38392, 21795 => 30504, 21796 => 26629, 21797 => 27048,
    851     21798 => 21643, 21799 => 20045, 21800 => 28856, 21801 => 35784, 21802 => 25688,
    852     21803 => 25995, 21804 => 23429, 21805 => 31364, 21806 => 20538, 21807 => 23528,
    853     21808 => 30651, 21809 => 27617, 21810 => 35449, 21811 => 31896, 21812 => 27838,
    854     21813 => 30415, 21814 => 26025, 21815 => 36759, 21816 => 23853, 21817 => 23637,
    855     21818 => 34360, 21819 => 26632, 21820 => 21344, 21821 => 25112, 21822 => 31449,
    856     21823 => 28251, 21824 => 32509, 21825 => 27167, 21826 => 31456, 21827 => 24432,
    857     21828 => 28467, 21829 => 24352, 21830 => 25484, 21831 => 28072, 21832 => 26454,
    858     21833 => 19976, 21834 => 24080, 21835 => 36134, 21836 => 20183, 21837 => 32960,
    859     21838 => 30260, 21839 => 38556, 21840 => 25307, 21841 => 26157, 21842 => 25214,
    860     21843 => 27836, 21844 => 36213, 21845 => 29031, 21846 => 32617, 21847 => 20806,
    861     21848 => 32903, 21849 => 21484, 21850 => 36974, 21851 => 25240, 21852 => 21746,
    862     21853 => 34544, 21854 => 36761, 21855 => 32773, 21856 => 38167, 21857 => 34071,
    863     21858 => 36825, 21859 => 27993, 21860 => 29645, 21861 => 26015, 21862 => 30495,
    864     21863 => 29956, 21864 => 30759, 21865 => 33275, 21866 => 36126, 21867 => 38024,
    865     21868 => 20390, 21869 => 26517, 21870 => 30137, 21871 => 35786, 21872 => 38663,
    866     21873 => 25391, 21874 => 38215, 21875 => 38453, 21876 => 33976, 21877 => 25379,
    867     21878 => 30529, 21879 => 24449, 21880 => 29424, 21881 => 20105, 21882 => 24596,
    868     21883 => 25972, 21884 => 25327, 21885 => 27491, 21886 => 25919, 22049 => 24103,
    869     22050 => 30151, 22051 => 37073, 22052 => 35777, 22053 => 33437, 22054 => 26525,
    870     22055 => 25903, 22056 => 21553, 22057 => 34584, 22058 => 30693, 22059 => 32930,
    871     22060 => 33026, 22061 => 27713, 22062 => 20043, 22063 => 32455, 22064 => 32844,
    872     22065 => 30452, 22066 => 26893, 22067 => 27542, 22068 => 25191, 22069 => 20540,
    873     22070 => 20356, 22071 => 22336, 22072 => 25351, 22073 => 27490, 22074 => 36286,
    874     22075 => 21482, 22076 => 26088, 22077 => 32440, 22078 => 24535, 22079 => 25370,
    875     22080 => 25527, 22081 => 33267, 22082 => 33268, 22083 => 32622, 22084 => 24092,
    876     22085 => 23769, 22086 => 21046, 22087 => 26234, 22088 => 31209, 22089 => 31258,
    877     22090 => 36136, 22091 => 28825, 22092 => 30164, 22093 => 28382, 22094 => 27835,
    878     22095 => 31378, 22096 => 20013, 22097 => 30405, 22098 => 24544, 22099 => 38047,
    879     22100 => 34935, 22101 => 32456, 22102 => 31181, 22103 => 32959, 22104 => 37325,
    880     22105 => 20210, 22106 => 20247, 22107 => 33311, 22108 => 21608, 22109 => 24030,
    881     22110 => 27954, 22111 => 35788, 22112 => 31909, 22113 => 36724, 22114 => 32920,
    882     22115 => 24090, 22116 => 21650, 22117 => 30385, 22118 => 23449, 22119 => 26172,
    883     22120 => 39588, 22121 => 29664, 22122 => 26666, 22123 => 34523, 22124 => 26417,
    884     22125 => 29482, 22126 => 35832, 22127 => 35803, 22128 => 36880, 22129 => 31481,
    885     22130 => 28891, 22131 => 29038, 22132 => 25284, 22133 => 30633, 22134 => 22065,
    886     22135 => 20027, 22136 => 33879, 22137 => 26609, 22138 => 21161, 22139 => 34496,
    887     22140 => 36142, 22141 => 38136, 22142 => 31569, 22305 => 20303, 22306 => 27880,
    888     22307 => 31069, 22308 => 39547, 22309 => 25235, 22310 => 29226, 22311 => 25341,
    889     22312 => 19987, 22313 => 30742, 22314 => 36716, 22315 => 25776, 22316 => 36186,
    890     22317 => 31686, 22318 => 26729, 22319 => 24196, 22320 => 35013, 22321 => 22918,
    891     22322 => 25758, 22323 => 22766, 22324 => 29366, 22325 => 26894, 22326 => 38181,
    892     22327 => 36861, 22328 => 36184, 22329 => 22368, 22330 => 32512, 22331 => 35846,
    893     22332 => 20934, 22333 => 25417, 22334 => 25305, 22335 => 21331, 22336 => 26700,
    894     22337 => 29730, 22338 => 33537, 22339 => 37196, 22340 => 21828, 22341 => 30528,
    895     22342 => 28796, 22343 => 27978, 22344 => 20857, 22345 => 21672, 22346 => 36164,
    896     22347 => 23039, 22348 => 28363, 22349 => 28100, 22350 => 23388, 22351 => 32043,
    897     22352 => 20180, 22353 => 31869, 22354 => 28371, 22355 => 23376, 22356 => 33258,
    898     22357 => 28173, 22358 => 23383, 22359 => 39683, 22360 => 26837, 22361 => 36394,
    899     22362 => 23447, 22363 => 32508, 22364 => 24635, 22365 => 32437, 22366 => 37049,
    900     22367 => 36208, 22368 => 22863, 22369 => 25549, 22370 => 31199, 22371 => 36275,
    901     22372 => 21330, 22373 => 26063, 22374 => 31062, 22375 => 35781, 22376 => 38459,
    902     22377 => 32452, 22378 => 38075, 22379 => 32386, 22380 => 22068, 22381 => 37257,
    903     22382 => 26368, 22383 => 32618, 22384 => 23562, 22385 => 36981, 22386 => 26152,
    904     22387 => 24038, 22388 => 20304, 22389 => 26590, 22390 => 20570, 22391 => 20316,
    905     22392 => 22352, 22393 => 24231, 22561 => 20109, 22562 => 19980, 22563 => 20800,
    906     22564 => 19984, 22565 => 24319, 22566 => 21317, 22567 => 19989, 22568 => 20120,
    907     22569 => 19998, 22570 => 39730, 22571 => 23404, 22572 => 22121, 22573 => 20008,
    908     22574 => 31162, 22575 => 20031, 22576 => 21269, 22577 => 20039, 22578 => 22829,
    909     22579 => 29243, 22580 => 21358, 22581 => 27664, 22582 => 22239, 22583 => 32996,
    910     22584 => 39319, 22585 => 27603, 22586 => 30590, 22587 => 40727, 22588 => 20022,
    911     22589 => 20127, 22590 => 40720, 22591 => 20060, 22592 => 20073, 22593 => 20115,
    912     22594 => 33416, 22595 => 23387, 22596 => 21868, 22597 => 22031, 22598 => 20164,
    913     22599 => 21389, 22600 => 21405, 22601 => 21411, 22602 => 21413, 22603 => 21422,
    914     22604 => 38757, 22605 => 36189, 22606 => 21274, 22607 => 21493, 22608 => 21286,
    915     22609 => 21294, 22610 => 21310, 22611 => 36188, 22612 => 21350, 22613 => 21347,
    916     22614 => 20994, 22615 => 21000, 22616 => 21006, 22617 => 21037, 22618 => 21043,
    917     22619 => 21055, 22620 => 21056, 22621 => 21068, 22622 => 21086, 22623 => 21089,
    918     22624 => 21084, 22625 => 33967, 22626 => 21117, 22627 => 21122, 22628 => 21121,
    919     22629 => 21136, 22630 => 21139, 22631 => 20866, 22632 => 32596, 22633 => 20155,
    920     22634 => 20163, 22635 => 20169, 22636 => 20162, 22637 => 20200, 22638 => 20193,
    921     22639 => 20203, 22640 => 20190, 22641 => 20251, 22642 => 20211, 22643 => 20258,
    922     22644 => 20324, 22645 => 20213, 22646 => 20261, 22647 => 20263, 22648 => 20233,
    923     22649 => 20267, 22650 => 20318, 22651 => 20327, 22652 => 25912, 22653 => 20314,
    924     22654 => 20317, 22817 => 20319, 22818 => 20311, 22819 => 20274, 22820 => 20285,
    925     22821 => 20342, 22822 => 20340, 22823 => 20369, 22824 => 20361, 22825 => 20355,
    926     22826 => 20367, 22827 => 20350, 22828 => 20347, 22829 => 20394, 22830 => 20348,
    927     22831 => 20396, 22832 => 20372, 22833 => 20454, 22834 => 20456, 22835 => 20458,
    928     22836 => 20421, 22837 => 20442, 22838 => 20451, 22839 => 20444, 22840 => 20433,
    929     22841 => 20447, 22842 => 20472, 22843 => 20521, 22844 => 20556, 22845 => 20467,
    930     22846 => 20524, 22847 => 20495, 22848 => 20526, 22849 => 20525, 22850 => 20478,
    931     22851 => 20508, 22852 => 20492, 22853 => 20517, 22854 => 20520, 22855 => 20606,
    932     22856 => 20547, 22857 => 20565, 22858 => 20552, 22859 => 20558, 22860 => 20588,
    933     22861 => 20603, 22862 => 20645, 22863 => 20647, 22864 => 20649, 22865 => 20666,
    934     22866 => 20694, 22867 => 20742, 22868 => 20717, 22869 => 20716, 22870 => 20710,
    935     22871 => 20718, 22872 => 20743, 22873 => 20747, 22874 => 20189, 22875 => 27709,
    936     22876 => 20312, 22877 => 20325, 22878 => 20430, 22879 => 40864, 22880 => 27718,
    937     22881 => 31860, 22882 => 20846, 22883 => 24061, 22884 => 40649, 22885 => 39320,
    938     22886 => 20865, 22887 => 22804, 22888 => 21241, 22889 => 21261, 22890 => 35335,
    939     22891 => 21264, 22892 => 20971, 22893 => 22809, 22894 => 20821, 22895 => 20128,
    940     22896 => 20822, 22897 => 20147, 22898 => 34926, 22899 => 34980, 22900 => 20149,
    941     22901 => 33044, 22902 => 35026, 22903 => 31104, 22904 => 23348, 22905 => 34819,
    942     22906 => 32696, 22907 => 20907, 22908 => 20913, 22909 => 20925, 22910 => 20924,
    943     23073 => 20935, 23074 => 20886, 23075 => 20898, 23076 => 20901, 23077 => 35744,
    944     23078 => 35750, 23079 => 35751, 23080 => 35754, 23081 => 35764, 23082 => 35765,
    945     23083 => 35767, 23084 => 35778, 23085 => 35779, 23086 => 35787, 23087 => 35791,
    946     23088 => 35790, 23089 => 35794, 23090 => 35795, 23091 => 35796, 23092 => 35798,
    947     23093 => 35800, 23094 => 35801, 23095 => 35804, 23096 => 35807, 23097 => 35808,
    948     23098 => 35812, 23099 => 35816, 23100 => 35817, 23101 => 35822, 23102 => 35824,
    949     23103 => 35827, 23104 => 35830, 23105 => 35833, 23106 => 35836, 23107 => 35839,
    950     23108 => 35840, 23109 => 35842, 23110 => 35844, 23111 => 35847, 23112 => 35852,
    951     23113 => 35855, 23114 => 35857, 23115 => 35858, 23116 => 35860, 23117 => 35861,
    952     23118 => 35862, 23119 => 35865, 23120 => 35867, 23121 => 35864, 23122 => 35869,
    953     23123 => 35871, 23124 => 35872, 23125 => 35873, 23126 => 35877, 23127 => 35879,
    954     23128 => 35882, 23129 => 35883, 23130 => 35886, 23131 => 35887, 23132 => 35890,
    955     23133 => 35891, 23134 => 35893, 23135 => 35894, 23136 => 21353, 23137 => 21370,
    956     23138 => 38429, 23139 => 38434, 23140 => 38433, 23141 => 38449, 23142 => 38442,
    957     23143 => 38461, 23144 => 38460, 23145 => 38466, 23146 => 38473, 23147 => 38484,
    958     23148 => 38495, 23149 => 38503, 23150 => 38508, 23151 => 38514, 23152 => 38516,
    959     23153 => 38536, 23154 => 38541, 23155 => 38551, 23156 => 38576, 23157 => 37015,
    960     23158 => 37019, 23159 => 37021, 23160 => 37017, 23161 => 37036, 23162 => 37025,
    961     23163 => 37044, 23164 => 37043, 23165 => 37046, 23166 => 37050, 23329 => 37048,
    962     23330 => 37040, 23331 => 37071, 23332 => 37061, 23333 => 37054, 23334 => 37072,
    963     23335 => 37060, 23336 => 37063, 23337 => 37075, 23338 => 37094, 23339 => 37090,
    964     23340 => 37084, 23341 => 37079, 23342 => 37083, 23343 => 37099, 23344 => 37103,
    965     23345 => 37118, 23346 => 37124, 23347 => 37154, 23348 => 37150, 23349 => 37155,
    966     23350 => 37169, 23351 => 37167, 23352 => 37177, 23353 => 37187, 23354 => 37190,
    967     23355 => 21005, 23356 => 22850, 23357 => 21154, 23358 => 21164, 23359 => 21165,
    968     23360 => 21182, 23361 => 21759, 23362 => 21200, 23363 => 21206, 23364 => 21232,
    969     23365 => 21471, 23366 => 29166, 23367 => 30669, 23368 => 24308, 23369 => 20981,
    970     23370 => 20988, 23371 => 39727, 23372 => 21430, 23373 => 24321, 23374 => 30042,
    971     23375 => 24047, 23376 => 22348, 23377 => 22441, 23378 => 22433, 23379 => 22654,
    972     23380 => 22716, 23381 => 22725, 23382 => 22737, 23383 => 22313, 23384 => 22316,
    973     23385 => 22314, 23386 => 22323, 23387 => 22329, 23388 => 22318, 23389 => 22319,
    974     23390 => 22364, 23391 => 22331, 23392 => 22338, 23393 => 22377, 23394 => 22405,
    975     23395 => 22379, 23396 => 22406, 23397 => 22396, 23398 => 22395, 23399 => 22376,
    976     23400 => 22381, 23401 => 22390, 23402 => 22387, 23403 => 22445, 23404 => 22436,
    977     23405 => 22412, 23406 => 22450, 23407 => 22479, 23408 => 22439, 23409 => 22452,
    978     23410 => 22419, 23411 => 22432, 23412 => 22485, 23413 => 22488, 23414 => 22490,
    979     23415 => 22489, 23416 => 22482, 23417 => 22456, 23418 => 22516, 23419 => 22511,
    980     23420 => 22520, 23421 => 22500, 23422 => 22493, 23585 => 22539, 23586 => 22541,
    981     23587 => 22525, 23588 => 22509, 23589 => 22528, 23590 => 22558, 23591 => 22553,
    982     23592 => 22596, 23593 => 22560, 23594 => 22629, 23595 => 22636, 23596 => 22657,
    983     23597 => 22665, 23598 => 22682, 23599 => 22656, 23600 => 39336, 23601 => 40729,
    984     23602 => 25087, 23603 => 33401, 23604 => 33405, 23605 => 33407, 23606 => 33423,
    985     23607 => 33418, 23608 => 33448, 23609 => 33412, 23610 => 33422, 23611 => 33425,
    986     23612 => 33431, 23613 => 33433, 23614 => 33451, 23615 => 33464, 23616 => 33470,
    987     23617 => 33456, 23618 => 33480, 23619 => 33482, 23620 => 33507, 23621 => 33432,
    988     23622 => 33463, 23623 => 33454, 23624 => 33483, 23625 => 33484, 23626 => 33473,
    989     23627 => 33449, 23628 => 33460, 23629 => 33441, 23630 => 33450, 23631 => 33439,
    990     23632 => 33476, 23633 => 33486, 23634 => 33444, 23635 => 33505, 23636 => 33545,
    991     23637 => 33527, 23638 => 33508, 23639 => 33551, 23640 => 33543, 23641 => 33500,
    992     23642 => 33524, 23643 => 33490, 23644 => 33496, 23645 => 33548, 23646 => 33531,
    993     23647 => 33491, 23648 => 33553, 23649 => 33562, 23650 => 33542, 23651 => 33556,
    994     23652 => 33557, 23653 => 33504, 23654 => 33493, 23655 => 33564, 23656 => 33617,
    995     23657 => 33627, 23658 => 33628, 23659 => 33544, 23660 => 33682, 23661 => 33596,
    996     23662 => 33588, 23663 => 33585, 23664 => 33691, 23665 => 33630, 23666 => 33583,
    997     23667 => 33615, 23668 => 33607, 23669 => 33603, 23670 => 33631, 23671 => 33600,
    998     23672 => 33559, 23673 => 33632, 23674 => 33581, 23675 => 33594, 23676 => 33587,
    999     23677 => 33638, 23678 => 33637, 23841 => 33640, 23842 => 33563, 23843 => 33641,
    1000     23844 => 33644, 23845 => 33642, 23846 => 33645, 23847 => 33646, 23848 => 33712,
    1001     23849 => 33656, 23850 => 33715, 23851 => 33716, 23852 => 33696, 23853 => 33706,
    1002     23854 => 33683, 23855 => 33692, 23856 => 33669, 23857 => 33660, 23858 => 33718,
    1003     23859 => 33705, 23860 => 33661, 23861 => 33720, 23862 => 33659, 23863 => 33688,
    1004     23864 => 33694, 23865 => 33704, 23866 => 33722, 23867 => 33724, 23868 => 33729,
    1005     23869 => 33793, 23870 => 33765, 23871 => 33752, 23872 => 22535, 23873 => 33816,
    1006     23874 => 33803, 23875 => 33757, 23876 => 33789, 23877 => 33750, 23878 => 33820,
    1007     23879 => 33848, 23880 => 33809, 23881 => 33798, 23882 => 33748, 23883 => 33759,
    1008     23884 => 33807, 23885 => 33795, 23886 => 33784, 23887 => 33785, 23888 => 33770,
    1009     23889 => 33733, 23890 => 33728, 23891 => 33830, 23892 => 33776, 23893 => 33761,
    1010     23894 => 33884, 23895 => 33873, 23896 => 33882, 23897 => 33881, 23898 => 33907,
    1011     23899 => 33927, 23900 => 33928, 23901 => 33914, 23902 => 33929, 23903 => 33912,
    1012     23904 => 33852, 23905 => 33862, 23906 => 33897, 23907 => 33910, 23908 => 33932,
    1013     23909 => 33934, 23910 => 33841, 23911 => 33901, 23912 => 33985, 23913 => 33997,
    1014     23914 => 34000, 23915 => 34022, 23916 => 33981, 23917 => 34003, 23918 => 33994,
    1015     23919 => 33983, 23920 => 33978, 23921 => 34016, 23922 => 33953, 23923 => 33977,
    1016     23924 => 33972, 23925 => 33943, 23926 => 34021, 23927 => 34019, 23928 => 34060,
    1017     23929 => 29965, 23930 => 34104, 23931 => 34032, 23932 => 34105, 23933 => 34079,
    1018     23934 => 34106, 24097 => 34134, 24098 => 34107, 24099 => 34047, 24100 => 34044,
    1019     24101 => 34137, 24102 => 34120, 24103 => 34152, 24104 => 34148, 24105 => 34142,
    1020     24106 => 34170, 24107 => 30626, 24108 => 34115, 24109 => 34162, 24110 => 34171,
    1021     24111 => 34212, 24112 => 34216, 24113 => 34183, 24114 => 34191, 24115 => 34169,
    1022     24116 => 34222, 24117 => 34204, 24118 => 34181, 24119 => 34233, 24120 => 34231,
    1023     24121 => 34224, 24122 => 34259, 24123 => 34241, 24124 => 34268, 24125 => 34303,
    1024     24126 => 34343, 24127 => 34309, 24128 => 34345, 24129 => 34326, 24130 => 34364,
    1025     24131 => 24318, 24132 => 24328, 24133 => 22844, 24134 => 22849, 24135 => 32823,
    1026     24136 => 22869, 24137 => 22874, 24138 => 22872, 24139 => 21263, 24140 => 23586,
    1027     24141 => 23589, 24142 => 23596, 24143 => 23604, 24144 => 25164, 24145 => 25194,
    1028     24146 => 25247, 24147 => 25275, 24148 => 25290, 24149 => 25306, 24150 => 25303,
    1029     24151 => 25326, 24152 => 25378, 24153 => 25334, 24154 => 25401, 24155 => 25419,
    1030     24156 => 25411, 24157 => 25517, 24158 => 25590, 24159 => 25457, 24160 => 25466,
    1031     24161 => 25486, 24162 => 25524, 24163 => 25453, 24164 => 25516, 24165 => 25482,
    1032     24166 => 25449, 24167 => 25518, 24168 => 25532, 24169 => 25586, 24170 => 25592,
    1033     24171 => 25568, 24172 => 25599, 24173 => 25540, 24174 => 25566, 24175 => 25550,
    1034     24176 => 25682, 24177 => 25542, 24178 => 25534, 24179 => 25669, 24180 => 25665,
    1035     24181 => 25611, 24182 => 25627, 24183 => 25632, 24184 => 25612, 24185 => 25638,
    1036     24186 => 25633, 24187 => 25694, 24188 => 25732, 24189 => 25709, 24190 => 25750,
    1037     24353 => 25722, 24354 => 25783, 24355 => 25784, 24356 => 25753, 24357 => 25786,
    1038     24358 => 25792, 24359 => 25808, 24360 => 25815, 24361 => 25828, 24362 => 25826,
    1039     24363 => 25865, 24364 => 25893, 24365 => 25902, 24366 => 24331, 24367 => 24530,
    1040     24368 => 29977, 24369 => 24337, 24370 => 21343, 24371 => 21489, 24372 => 21501,
    1041     24373 => 21481, 24374 => 21480, 24375 => 21499, 24376 => 21522, 24377 => 21526,
    1042     24378 => 21510, 24379 => 21579, 24380 => 21586, 24381 => 21587, 24382 => 21588,
    1043     24383 => 21590, 24384 => 21571, 24385 => 21537, 24386 => 21591, 24387 => 21593,
    1044     24388 => 21539, 24389 => 21554, 24390 => 21634, 24391 => 21652, 24392 => 21623,
    1045     24393 => 21617, 24394 => 21604, 24395 => 21658, 24396 => 21659, 24397 => 21636,
    1046     24398 => 21622, 24399 => 21606, 24400 => 21661, 24401 => 21712, 24402 => 21677,
    1047     24403 => 21698, 24404 => 21684, 24405 => 21714, 24406 => 21671, 24407 => 21670,
    1048     24408 => 21715, 24409 => 21716, 24410 => 21618, 24411 => 21667, 24412 => 21717,
    1049     24413 => 21691, 24414 => 21695, 24415 => 21708, 24416 => 21721, 24417 => 21722,
    1050     24418 => 21724, 24419 => 21673, 24420 => 21674, 24421 => 21668, 24422 => 21725,
    1051     24423 => 21711, 24424 => 21726, 24425 => 21787, 24426 => 21735, 24427 => 21792,
    1052     24428 => 21757, 24429 => 21780, 24430 => 21747, 24431 => 21794, 24432 => 21795,
    1053     24433 => 21775, 24434 => 21777, 24435 => 21799, 24436 => 21802, 24437 => 21863,
    1054     24438 => 21903, 24439 => 21941, 24440 => 21833, 24441 => 21869, 24442 => 21825,
    1055     24443 => 21845, 24444 => 21823, 24445 => 21840, 24446 => 21820, 24609 => 21815,
    1056     24610 => 21846, 24611 => 21877, 24612 => 21878, 24613 => 21879, 24614 => 21811,
    1057     24615 => 21808, 24616 => 21852, 24617 => 21899, 24618 => 21970, 24619 => 21891,
    1058     24620 => 21937, 24621 => 21945, 24622 => 21896, 24623 => 21889, 24624 => 21919,
    1059     24625 => 21886, 24626 => 21974, 24627 => 21905, 24628 => 21883, 24629 => 21983,
    1060     24630 => 21949, 24631 => 21950, 24632 => 21908, 24633 => 21913, 24634 => 21994,
    1061     24635 => 22007, 24636 => 21961, 24637 => 22047, 24638 => 21969, 24639 => 21995,
    1062     24640 => 21996, 24641 => 21972, 24642 => 21990, 24643 => 21981, 24644 => 21956,
    1063     24645 => 21999, 24646 => 21989, 24647 => 22002, 24648 => 22003, 24649 => 21964,
    1064     24650 => 21965, 24651 => 21992, 24652 => 22005, 24653 => 21988, 24654 => 36756,
    1065     24655 => 22046, 24656 => 22024, 24657 => 22028, 24658 => 22017, 24659 => 22052,
    1066     24660 => 22051, 24661 => 22014, 24662 => 22016, 24663 => 22055, 24664 => 22061,
    1067     24665 => 22104, 24666 => 22073, 24667 => 22103, 24668 => 22060, 24669 => 22093,
    1068     24670 => 22114, 24671 => 22105, 24672 => 22108, 24673 => 22092, 24674 => 22100,
    1069     24675 => 22150, 24676 => 22116, 24677 => 22129, 24678 => 22123, 24679 => 22139,
    1070     24680 => 22140, 24681 => 22149, 24682 => 22163, 24683 => 22191, 24684 => 22228,
    1071     24685 => 22231, 24686 => 22237, 24687 => 22241, 24688 => 22261, 24689 => 22251,
    1072     24690 => 22265, 24691 => 22271, 24692 => 22276, 24693 => 22282, 24694 => 22281,
    1073     24695 => 22300, 24696 => 24079, 24697 => 24089, 24698 => 24084, 24699 => 24081,
    1074     24700 => 24113, 24701 => 24123, 24702 => 24124, 24865 => 24119, 24866 => 24132,
    1075     24867 => 24148, 24868 => 24155, 24869 => 24158, 24870 => 24161, 24871 => 23692,
    1076     24872 => 23674, 24873 => 23693, 24874 => 23696, 24875 => 23702, 24876 => 23688,
    1077     24877 => 23704, 24878 => 23705, 24879 => 23697, 24880 => 23706, 24881 => 23708,
    1078     24882 => 23733, 24883 => 23714, 24884 => 23741, 24885 => 23724, 24886 => 23723,
    1079     24887 => 23729, 24888 => 23715, 24889 => 23745, 24890 => 23735, 24891 => 23748,
    1080     24892 => 23762, 24893 => 23780, 24894 => 23755, 24895 => 23781, 24896 => 23810,
    1081     24897 => 23811, 24898 => 23847, 24899 => 23846, 24900 => 23854, 24901 => 23844,
    1082     24902 => 23838, 24903 => 23814, 24904 => 23835, 24905 => 23896, 24906 => 23870,
    1083     24907 => 23860, 24908 => 23869, 24909 => 23916, 24910 => 23899, 24911 => 23919,
    1084     24912 => 23901, 24913 => 23915, 24914 => 23883, 24915 => 23882, 24916 => 23913,
    1085     24917 => 23924, 24918 => 23938, 24919 => 23961, 24920 => 23965, 24921 => 35955,
    1086     24922 => 23991, 24923 => 24005, 24924 => 24435, 24925 => 24439, 24926 => 24450,
    1087     24927 => 24455, 24928 => 24457, 24929 => 24460, 24930 => 24469, 24931 => 24473,
    1088     24932 => 24476, 24933 => 24488, 24934 => 24493, 24935 => 24501, 24936 => 24508,
    1089     24937 => 34914, 24938 => 24417, 24939 => 29357, 24940 => 29360, 24941 => 29364,
    1090     24942 => 29367, 24943 => 29368, 24944 => 29379, 24945 => 29377, 24946 => 29390,
    1091     24947 => 29389, 24948 => 29394, 24949 => 29416, 24950 => 29423, 24951 => 29417,
    1092     24952 => 29426, 24953 => 29428, 24954 => 29431, 24955 => 29441, 24956 => 29427,
    1093     24957 => 29443, 24958 => 29434, 25121 => 29435, 25122 => 29463, 25123 => 29459,
    1094     25124 => 29473, 25125 => 29450, 25126 => 29470, 25127 => 29469, 25128 => 29461,
    1095     25129 => 29474, 25130 => 29497, 25131 => 29477, 25132 => 29484, 25133 => 29496,
    1096     25134 => 29489, 25135 => 29520, 25136 => 29517, 25137 => 29527, 25138 => 29536,
    1097     25139 => 29548, 25140 => 29551, 25141 => 29566, 25142 => 33307, 25143 => 22821,
    1098     25144 => 39143, 25145 => 22820, 25146 => 22786, 25147 => 39267, 25148 => 39271,
    1099     25149 => 39272, 25150 => 39273, 25151 => 39274, 25152 => 39275, 25153 => 39276,
    1100     25154 => 39284, 25155 => 39287, 25156 => 39293, 25157 => 39296, 25158 => 39300,
    1101     25159 => 39303, 25160 => 39306, 25161 => 39309, 25162 => 39312, 25163 => 39313,
    1102     25164 => 39315, 25165 => 39316, 25166 => 39317, 25167 => 24192, 25168 => 24209,
    1103     25169 => 24203, 25170 => 24214, 25171 => 24229, 25172 => 24224, 25173 => 24249,
    1104     25174 => 24245, 25175 => 24254, 25176 => 24243, 25177 => 36179, 25178 => 24274,
    1105     25179 => 24273, 25180 => 24283, 25181 => 24296, 25182 => 24298, 25183 => 33210,
    1106     25184 => 24516, 25185 => 24521, 25186 => 24534, 25187 => 24527, 25188 => 24579,
    1107     25189 => 24558, 25190 => 24580, 25191 => 24545, 25192 => 24548, 25193 => 24574,
    1108     25194 => 24581, 25195 => 24582, 25196 => 24554, 25197 => 24557, 25198 => 24568,
    1109     25199 => 24601, 25200 => 24629, 25201 => 24614, 25202 => 24603, 25203 => 24591,
    1110     25204 => 24589, 25205 => 24617, 25206 => 24619, 25207 => 24586, 25208 => 24639,
    1111     25209 => 24609, 25210 => 24696, 25211 => 24697, 25212 => 24699, 25213 => 24698,
    1112     25214 => 24642, 25377 => 24682, 25378 => 24701, 25379 => 24726, 25380 => 24730,
    1113     25381 => 24749, 25382 => 24733, 25383 => 24707, 25384 => 24722, 25385 => 24716,
    1114     25386 => 24731, 25387 => 24812, 25388 => 24763, 25389 => 24753, 25390 => 24797,
    1115     25391 => 24792, 25392 => 24774, 25393 => 24794, 25394 => 24756, 25395 => 24864,
    1116     25396 => 24870, 25397 => 24853, 25398 => 24867, 25399 => 24820, 25400 => 24832,
    1117     25401 => 24846, 25402 => 24875, 25403 => 24906, 25404 => 24949, 25405 => 25004,
    1118     25406 => 24980, 25407 => 24999, 25408 => 25015, 25409 => 25044, 25410 => 25077,
    1119     25411 => 24541, 25412 => 38579, 25413 => 38377, 25414 => 38379, 25415 => 38385,
    1120     25416 => 38387, 25417 => 38389, 25418 => 38390, 25419 => 38396, 25420 => 38398,
    1121     25421 => 38403, 25422 => 38404, 25423 => 38406, 25424 => 38408, 25425 => 38410,
    1122     25426 => 38411, 25427 => 38412, 25428 => 38413, 25429 => 38415, 25430 => 38418,
    1123     25431 => 38421, 25432 => 38422, 25433 => 38423, 25434 => 38425, 25435 => 38426,
    1124     25436 => 20012, 25437 => 29247, 25438 => 25109, 25439 => 27701, 25440 => 27732,
    1125     25441 => 27740, 25442 => 27722, 25443 => 27811, 25444 => 27781, 25445 => 27792,
    1126     25446 => 27796, 25447 => 27788, 25448 => 27752, 25449 => 27753, 25450 => 27764,
    1127     25451 => 27766, 25452 => 27782, 25453 => 27817, 25454 => 27856, 25455 => 27860,
    1128     25456 => 27821, 25457 => 27895, 25458 => 27896, 25459 => 27889, 25460 => 27863,
    1129     25461 => 27826, 25462 => 27872, 25463 => 27862, 25464 => 27898, 25465 => 27883,
    1130     25466 => 27886, 25467 => 27825, 25468 => 27859, 25469 => 27887, 25470 => 27902,
    1131     25633 => 27961, 25634 => 27943, 25635 => 27916, 25636 => 27971, 25637 => 27976,
    1132     25638 => 27911, 25639 => 27908, 25640 => 27929, 25641 => 27918, 25642 => 27947,
    1133     25643 => 27981, 25644 => 27950, 25645 => 27957, 25646 => 27930, 25647 => 27983,
    1134     25648 => 27986, 25649 => 27988, 25650 => 27955, 25651 => 28049, 25652 => 28015,
    1135     25653 => 28062, 25654 => 28064, 25655 => 27998, 25656 => 28051, 25657 => 28052,
    1136     25658 => 27996, 25659 => 28000, 25660 => 28028, 25661 => 28003, 25662 => 28186,
    1137     25663 => 28103, 25664 => 28101, 25665 => 28126, 25666 => 28174, 25667 => 28095,
    1138     25668 => 28128, 25669 => 28177, 25670 => 28134, 25671 => 28125, 25672 => 28121,
    1139     25673 => 28182, 25674 => 28075, 25675 => 28172, 25676 => 28078, 25677 => 28203,
    1140     25678 => 28270, 25679 => 28238, 25680 => 28267, 25681 => 28338, 25682 => 28255,
    1141     25683 => 28294, 25684 => 28243, 25685 => 28244, 25686 => 28210, 25687 => 28197,
    1142     25688 => 28228, 25689 => 28383, 25690 => 28337, 25691 => 28312, 25692 => 28384,
    1143     25693 => 28461, 25694 => 28386, 25695 => 28325, 25696 => 28327, 25697 => 28349,
    1144     25698 => 28347, 25699 => 28343, 25700 => 28375, 25701 => 28340, 25702 => 28367,
    1145     25703 => 28303, 25704 => 28354, 25705 => 28319, 25706 => 28514, 25707 => 28486,
    1146     25708 => 28487, 25709 => 28452, 25710 => 28437, 25711 => 28409, 25712 => 28463,
    1147     25713 => 28470, 25714 => 28491, 25715 => 28532, 25716 => 28458, 25717 => 28425,
    1148     25718 => 28457, 25719 => 28553, 25720 => 28557, 25721 => 28556, 25722 => 28536,
    1149     25723 => 28530, 25724 => 28540, 25725 => 28538, 25726 => 28625, 25889 => 28617,
    1150     25890 => 28583, 25891 => 28601, 25892 => 28598, 25893 => 28610, 25894 => 28641,
    1151     25895 => 28654, 25896 => 28638, 25897 => 28640, 25898 => 28655, 25899 => 28698,
    1152     25900 => 28707, 25901 => 28699, 25902 => 28729, 25903 => 28725, 25904 => 28751,
    1153     25905 => 28766, 25906 => 23424, 25907 => 23428, 25908 => 23445, 25909 => 23443,
    1154     25910 => 23461, 25911 => 23480, 25912 => 29999, 25913 => 39582, 25914 => 25652,
    1155     25915 => 23524, 25916 => 23534, 25917 => 35120, 25918 => 23536, 25919 => 36423,
    1156     25920 => 35591, 25921 => 36790, 25922 => 36819, 25923 => 36821, 25924 => 36837,
    1157     25925 => 36846, 25926 => 36836, 25927 => 36841, 25928 => 36838, 25929 => 36851,
    1158     25930 => 36840, 25931 => 36869, 25932 => 36868, 25933 => 36875, 25934 => 36902,
    1159     25935 => 36881, 25936 => 36877, 25937 => 36886, 25938 => 36897, 25939 => 36917,
    1160     25940 => 36918, 25941 => 36909, 25942 => 36911, 25943 => 36932, 25944 => 36945,
    1161     25945 => 36946, 25946 => 36944, 25947 => 36968, 25948 => 36952, 25949 => 36962,
    1162     25950 => 36955, 25951 => 26297, 25952 => 36980, 25953 => 36989, 25954 => 36994,
    1163     25955 => 37000, 25956 => 36995, 25957 => 37003, 25958 => 24400, 25959 => 24407,
    1164     25960 => 24406, 25961 => 24408, 25962 => 23611, 25963 => 21675, 25964 => 23632,
    1165     25965 => 23641, 25966 => 23409, 25967 => 23651, 25968 => 23654, 25969 => 32700,
    1166     25970 => 24362, 25971 => 24361, 25972 => 24365, 25973 => 33396, 25974 => 24380,
    1167     25975 => 39739, 25976 => 23662, 25977 => 22913, 25978 => 22915, 25979 => 22925,
    1168     25980 => 22953, 25981 => 22954, 25982 => 22947, 26145 => 22935, 26146 => 22986,
    1169     26147 => 22955, 26148 => 22942, 26149 => 22948, 26150 => 22994, 26151 => 22962,
    1170     26152 => 22959, 26153 => 22999, 26154 => 22974, 26155 => 23045, 26156 => 23046,
    1171     26157 => 23005, 26158 => 23048, 26159 => 23011, 26160 => 23000, 26161 => 23033,
    1172     26162 => 23052, 26163 => 23049, 26164 => 23090, 26165 => 23092, 26166 => 23057,
    1173     26167 => 23075, 26168 => 23059, 26169 => 23104, 26170 => 23143, 26171 => 23114,
    1174     26172 => 23125, 26173 => 23100, 26174 => 23138, 26175 => 23157, 26176 => 33004,
    1175     26177 => 23210, 26178 => 23195, 26179 => 23159, 26180 => 23162, 26181 => 23230,
    1176     26182 => 23275, 26183 => 23218, 26184 => 23250, 26185 => 23252, 26186 => 23224,
    1177     26187 => 23264, 26188 => 23267, 26189 => 23281, 26190 => 23254, 26191 => 23270,
    1178     26192 => 23256, 26193 => 23260, 26194 => 23305, 26195 => 23319, 26196 => 23318,
    1179     26197 => 23346, 26198 => 23351, 26199 => 23360, 26200 => 23573, 26201 => 23580,
    1180     26202 => 23386, 26203 => 23397, 26204 => 23411, 26205 => 23377, 26206 => 23379,
    1181     26207 => 23394, 26208 => 39541, 26209 => 39543, 26210 => 39544, 26211 => 39546,
    1182     26212 => 39551, 26213 => 39549, 26214 => 39552, 26215 => 39553, 26216 => 39557,
    1183     26217 => 39560, 26218 => 39562, 26219 => 39568, 26220 => 39570, 26221 => 39571,
    1184     26222 => 39574, 26223 => 39576, 26224 => 39579, 26225 => 39580, 26226 => 39581,
    1185     26227 => 39583, 26228 => 39584, 26229 => 39586, 26230 => 39587, 26231 => 39589,
    1186     26232 => 39591, 26233 => 32415, 26234 => 32417, 26235 => 32419, 26236 => 32421,
    1187     26237 => 32424, 26238 => 32425, 26401 => 32429, 26402 => 32432, 26403 => 32446,
    1188     26404 => 32448, 26405 => 32449, 26406 => 32450, 26407 => 32457, 26408 => 32459,
    1189     26409 => 32460, 26410 => 32464, 26411 => 32468, 26412 => 32471, 26413 => 32475,
    1190     26414 => 32480, 26415 => 32481, 26416 => 32488, 26417 => 32491, 26418 => 32494,
    1191     26419 => 32495, 26420 => 32497, 26421 => 32498, 26422 => 32525, 26423 => 32502,
    1192     26424 => 32506, 26425 => 32507, 26426 => 32510, 26427 => 32513, 26428 => 32514,
    1193     26429 => 32515, 26430 => 32519, 26431 => 32520, 26432 => 32523, 26433 => 32524,
    1194     26434 => 32527, 26435 => 32529, 26436 => 32530, 26437 => 32535, 26438 => 32537,
    1195     26439 => 32540, 26440 => 32539, 26441 => 32543, 26442 => 32545, 26443 => 32546,
    1196     26444 => 32547, 26445 => 32548, 26446 => 32549, 26447 => 32550, 26448 => 32551,
    1197     26449 => 32554, 26450 => 32555, 26451 => 32556, 26452 => 32557, 26453 => 32559,
    1198     26454 => 32560, 26455 => 32561, 26456 => 32562, 26457 => 32563, 26458 => 32565,
    1199     26459 => 24186, 26460 => 30079, 26461 => 24027, 26462 => 30014, 26463 => 37013,
    1200     26464 => 29582, 26465 => 29585, 26466 => 29614, 26467 => 29602, 26468 => 29599,
    1201     26469 => 29647, 26470 => 29634, 26471 => 29649, 26472 => 29623, 26473 => 29619,
    1202     26474 => 29632, 26475 => 29641, 26476 => 29640, 26477 => 29669, 26478 => 29657,
    1203     26479 => 39036, 26480 => 29706, 26481 => 29673, 26482 => 29671, 26483 => 29662,
    1204     26484 => 29626, 26485 => 29682, 26486 => 29711, 26487 => 29738, 26488 => 29787,
    1205     26489 => 29734, 26490 => 29733, 26491 => 29736, 26492 => 29744, 26493 => 29742,
    1206     26494 => 29740, 26657 => 29723, 26658 => 29722, 26659 => 29761, 26660 => 29788,
    1207     26661 => 29783, 26662 => 29781, 26663 => 29785, 26664 => 29815, 26665 => 29805,
    1208     26666 => 29822, 26667 => 29852, 26668 => 29838, 26669 => 29824, 26670 => 29825,
    1209     26671 => 29831, 26672 => 29835, 26673 => 29854, 26674 => 29864, 26675 => 29865,
    1210     26676 => 29840, 26677 => 29863, 26678 => 29906, 26679 => 29882, 26680 => 38890,
    1211     26681 => 38891, 26682 => 38892, 26683 => 26444, 26684 => 26451, 26685 => 26462,
    1212     26686 => 26440, 26687 => 26473, 26688 => 26533, 26689 => 26503, 26690 => 26474,
    1213     26691 => 26483, 26692 => 26520, 26693 => 26535, 26694 => 26485, 26695 => 26536,
    1214     26696 => 26526, 26697 => 26541, 26698 => 26507, 26699 => 26487, 26700 => 26492,
    1215     26701 => 26608, 26702 => 26633, 26703 => 26584, 26704 => 26634, 26705 => 26601,
    1216     26706 => 26544, 26707 => 26636, 26708 => 26585, 26709 => 26549, 26710 => 26586,
    1217     26711 => 26547, 26712 => 26589, 26713 => 26624, 26714 => 26563, 26715 => 26552,
    1218     26716 => 26594, 26717 => 26638, 26718 => 26561, 26719 => 26621, 26720 => 26674,
    1219     26721 => 26675, 26722 => 26720, 26723 => 26721, 26724 => 26702, 26725 => 26722,
    1220     26726 => 26692, 26727 => 26724, 26728 => 26755, 26729 => 26653, 26730 => 26709,
    1221     26731 => 26726, 26732 => 26689, 26733 => 26727, 26734 => 26688, 26735 => 26686,
    1222     26736 => 26698, 26737 => 26697, 26738 => 26665, 26739 => 26805, 26740 => 26767,
    1223     26741 => 26740, 26742 => 26743, 26743 => 26771, 26744 => 26731, 26745 => 26818,
    1224     26746 => 26990, 26747 => 26876, 26748 => 26911, 26749 => 26912, 26750 => 26873,
    1225     26913 => 26916, 26914 => 26864, 26915 => 26891, 26916 => 26881, 26917 => 26967,
    1226     26918 => 26851, 26919 => 26896, 26920 => 26993, 26921 => 26937, 26922 => 26976,
    1227     26923 => 26946, 26924 => 26973, 26925 => 27012, 26926 => 26987, 26927 => 27008,
    1228     26928 => 27032, 26929 => 27000, 26930 => 26932, 26931 => 27084, 26932 => 27015,
    1229     26933 => 27016, 26934 => 27086, 26935 => 27017, 26936 => 26982, 26937 => 26979,
    1230     26938 => 27001, 26939 => 27035, 26940 => 27047, 26941 => 27067, 26942 => 27051,
    1231     26943 => 27053, 26944 => 27092, 26945 => 27057, 26946 => 27073, 26947 => 27082,
    1232     26948 => 27103, 26949 => 27029, 26950 => 27104, 26951 => 27021, 26952 => 27135,
    1233     26953 => 27183, 26954 => 27117, 26955 => 27159, 26956 => 27160, 26957 => 27237,
    1234     26958 => 27122, 26959 => 27204, 26960 => 27198, 26961 => 27296, 26962 => 27216,
    1235     26963 => 27227, 26964 => 27189, 26965 => 27278, 26966 => 27257, 26967 => 27197,
    1236     26968 => 27176, 26969 => 27224, 26970 => 27260, 26971 => 27281, 26972 => 27280,
    1237     26973 => 27305, 26974 => 27287, 26975 => 27307, 26976 => 29495, 26977 => 29522,
    1238     26978 => 27521, 26979 => 27522, 26980 => 27527, 26981 => 27524, 26982 => 27538,
    1239     26983 => 27539, 26984 => 27533, 26985 => 27546, 26986 => 27547, 26987 => 27553,
    1240     26988 => 27562, 26989 => 36715, 26990 => 36717, 26991 => 36721, 26992 => 36722,
    1241     26993 => 36723, 26994 => 36725, 26995 => 36726, 26996 => 36728, 26997 => 36727,
    1242     26998 => 36729, 26999 => 36730, 27000 => 36732, 27001 => 36734, 27002 => 36737,
    1243     27003 => 36738, 27004 => 36740, 27005 => 36743, 27006 => 36747, 27169 => 36749,
    1244     27170 => 36750, 27171 => 36751, 27172 => 36760, 27173 => 36762, 27174 => 36558,
    1245     27175 => 25099, 27176 => 25111, 27177 => 25115, 27178 => 25119, 27179 => 25122,
    1246     27180 => 25121, 27181 => 25125, 27182 => 25124, 27183 => 25132, 27184 => 33255,
    1247     27185 => 29935, 27186 => 29940, 27187 => 29951, 27188 => 29967, 27189 => 29969,
    1248     27190 => 29971, 27191 => 25908, 27192 => 26094, 27193 => 26095, 27194 => 26096,
    1249     27195 => 26122, 27196 => 26137, 27197 => 26482, 27198 => 26115, 27199 => 26133,
    1250     27200 => 26112, 27201 => 28805, 27202 => 26359, 27203 => 26141, 27204 => 26164,
    1251     27205 => 26161, 27206 => 26166, 27207 => 26165, 27208 => 32774, 27209 => 26207,
    1252     27210 => 26196, 27211 => 26177, 27212 => 26191, 27213 => 26198, 27214 => 26209,
    1253     27215 => 26199, 27216 => 26231, 27217 => 26244, 27218 => 26252, 27219 => 26279,
    1254     27220 => 26269, 27221 => 26302, 27222 => 26331, 27223 => 26332, 27224 => 26342,
    1255     27225 => 26345, 27226 => 36146, 27227 => 36147, 27228 => 36150, 27229 => 36155,
    1256     27230 => 36157, 27231 => 36160, 27232 => 36165, 27233 => 36166, 27234 => 36168,
    1257     27235 => 36169, 27236 => 36167, 27237 => 36173, 27238 => 36181, 27239 => 36185,
    1258     27240 => 35271, 27241 => 35274, 27242 => 35275, 27243 => 35276, 27244 => 35278,
    1259     27245 => 35279, 27246 => 35280, 27247 => 35281, 27248 => 29294, 27249 => 29343,
    1260     27250 => 29277, 27251 => 29286, 27252 => 29295, 27253 => 29310, 27254 => 29311,
    1261     27255 => 29316, 27256 => 29323, 27257 => 29325, 27258 => 29327, 27259 => 29330,
    1262     27260 => 25352, 27261 => 25394, 27262 => 25520, 27425 => 25663, 27426 => 25816,
    1263     27427 => 32772, 27428 => 27626, 27429 => 27635, 27430 => 27645, 27431 => 27637,
    1264     27432 => 27641, 27433 => 27653, 27434 => 27655, 27435 => 27654, 27436 => 27661,
    1265     27437 => 27669, 27438 => 27672, 27439 => 27673, 27440 => 27674, 27441 => 27681,
    1266     27442 => 27689, 27443 => 27684, 27444 => 27690, 27445 => 27698, 27446 => 25909,
    1267     27447 => 25941, 27448 => 25963, 27449 => 29261, 27450 => 29266, 27451 => 29270,
    1268     27452 => 29232, 27453 => 34402, 27454 => 21014, 27455 => 32927, 27456 => 32924,
    1269     27457 => 32915, 27458 => 32956, 27459 => 26378, 27460 => 32957, 27461 => 32945,
    1270     27462 => 32939, 27463 => 32941, 27464 => 32948, 27465 => 32951, 27466 => 32999,
    1271     27467 => 33000, 27468 => 33001, 27469 => 33002, 27470 => 32987, 27471 => 32962,
    1272     27472 => 32964, 27473 => 32985, 27474 => 32973, 27475 => 32983, 27476 => 26384,
    1273     27477 => 32989, 27478 => 33003, 27479 => 33009, 27480 => 33012, 27481 => 33005,
    1274     27482 => 33037, 27483 => 33038, 27484 => 33010, 27485 => 33020, 27486 => 26389,
    1275     27487 => 33042, 27488 => 35930, 27489 => 33078, 27490 => 33054, 27491 => 33068,
    1276     27492 => 33048, 27493 => 33074, 27494 => 33096, 27495 => 33100, 27496 => 33107,
    1277     27497 => 33140, 27498 => 33113, 27499 => 33114, 27500 => 33137, 27501 => 33120,
    1278     27502 => 33129, 27503 => 33148, 27504 => 33149, 27505 => 33133, 27506 => 33127,
    1279     27507 => 22605, 27508 => 23221, 27509 => 33160, 27510 => 33154, 27511 => 33169,
    1280     27512 => 28373, 27513 => 33187, 27514 => 33194, 27515 => 33228, 27516 => 26406,
    1281     27517 => 33226, 27518 => 33211, 27681 => 33217, 27682 => 33190, 27683 => 27428,
    1282     27684 => 27447, 27685 => 27449, 27686 => 27459, 27687 => 27462, 27688 => 27481,
    1283     27689 => 39121, 27690 => 39122, 27691 => 39123, 27692 => 39125, 27693 => 39129,
    1284     27694 => 39130, 27695 => 27571, 27696 => 24384, 27697 => 27586, 27698 => 35315,
    1285     27699 => 26000, 27700 => 40785, 27701 => 26003, 27702 => 26044, 27703 => 26054,
    1286     27704 => 26052, 27705 => 26051, 27706 => 26060, 27707 => 26062, 27708 => 26066,
    1287     27709 => 26070, 27710 => 28800, 27711 => 28828, 27712 => 28822, 27713 => 28829,
    1288     27714 => 28859, 27715 => 28864, 27716 => 28855, 27717 => 28843, 27718 => 28849,
    1289     27719 => 28904, 27720 => 28874, 27721 => 28944, 27722 => 28947, 27723 => 28950,
    1290     27724 => 28975, 27725 => 28977, 27726 => 29043, 27727 => 29020, 27728 => 29032,
    1291     27729 => 28997, 27730 => 29042, 27731 => 29002, 27732 => 29048, 27733 => 29050,
    1292     27734 => 29080, 27735 => 29107, 27736 => 29109, 27737 => 29096, 27738 => 29088,
    1293     27739 => 29152, 27740 => 29140, 27741 => 29159, 27742 => 29177, 27743 => 29213,
    1294     27744 => 29224, 27745 => 28780, 27746 => 28952, 27747 => 29030, 27748 => 29113,
    1295     27749 => 25150, 27750 => 25149, 27751 => 25155, 27752 => 25160, 27753 => 25161,
    1296     27754 => 31035, 27755 => 31040, 27756 => 31046, 27757 => 31049, 27758 => 31067,
    1297     27759 => 31068, 27760 => 31059, 27761 => 31066, 27762 => 31074, 27763 => 31063,
    1298     27764 => 31072, 27765 => 31087, 27766 => 31079, 27767 => 31098, 27768 => 31109,
    1299     27769 => 31114, 27770 => 31130, 27771 => 31143, 27772 => 31155, 27773 => 24529,
    1300     27774 => 24528, 27937 => 24636, 27938 => 24669, 27939 => 24666, 27940 => 24679,
    1301     27941 => 24641, 27942 => 24665, 27943 => 24675, 27944 => 24747, 27945 => 24838,
    1302     27946 => 24845, 27947 => 24925, 27948 => 25001, 27949 => 24989, 27950 => 25035,
    1303     27951 => 25041, 27952 => 25094, 27953 => 32896, 27954 => 32895, 27955 => 27795,
    1304     27956 => 27894, 27957 => 28156, 27958 => 30710, 27959 => 30712, 27960 => 30720,
    1305     27961 => 30729, 27962 => 30743, 27963 => 30744, 27964 => 30737, 27965 => 26027,
    1306     27966 => 30765, 27967 => 30748, 27968 => 30749, 27969 => 30777, 27970 => 30778,
    1307     27971 => 30779, 27972 => 30751, 27973 => 30780, 27974 => 30757, 27975 => 30764,
    1308     27976 => 30755, 27977 => 30761, 27978 => 30798, 27979 => 30829, 27980 => 30806,
    1309     27981 => 30807, 27982 => 30758, 27983 => 30800, 27984 => 30791, 27985 => 30796,
    1310     27986 => 30826, 27987 => 30875, 27988 => 30867, 27989 => 30874, 27990 => 30855,
    1311     27991 => 30876, 27992 => 30881, 27993 => 30883, 27994 => 30898, 27995 => 30905,
    1312     27996 => 30885, 27997 => 30932, 27998 => 30937, 27999 => 30921, 28000 => 30956,
    1313     28001 => 30962, 28002 => 30981, 28003 => 30964, 28004 => 30995, 28005 => 31012,
    1314     28006 => 31006, 28007 => 31028, 28008 => 40859, 28009 => 40697, 28010 => 40699,
    1315     28011 => 40700, 28012 => 30449, 28013 => 30468, 28014 => 30477, 28015 => 30457,
    1316     28016 => 30471, 28017 => 30472, 28018 => 30490, 28019 => 30498, 28020 => 30489,
    1317     28021 => 30509, 28022 => 30502, 28023 => 30517, 28024 => 30520, 28025 => 30544,
    1318     28026 => 30545, 28027 => 30535, 28028 => 30531, 28029 => 30554, 28030 => 30568,
    1319     28193 => 30562, 28194 => 30565, 28195 => 30591, 28196 => 30605, 28197 => 30589,
    1320     28198 => 30592, 28199 => 30604, 28200 => 30609, 28201 => 30623, 28202 => 30624,
    1321     28203 => 30640, 28204 => 30645, 28205 => 30653, 28206 => 30010, 28207 => 30016,
    1322     28208 => 30030, 28209 => 30027, 28210 => 30024, 28211 => 30043, 28212 => 30066,
    1323     28213 => 30073, 28214 => 30083, 28215 => 32600, 28216 => 32609, 28217 => 32607,
    1324     28218 => 35400, 28219 => 32616, 28220 => 32628, 28221 => 32625, 28222 => 32633,
    1325     28223 => 32641, 28224 => 32638, 28225 => 30413, 28226 => 30437, 28227 => 34866,
    1326     28228 => 38021, 28229 => 38022, 28230 => 38023, 28231 => 38027, 28232 => 38026,
    1327     28233 => 38028, 28234 => 38029, 28235 => 38031, 28236 => 38032, 28237 => 38036,
    1328     28238 => 38039, 28239 => 38037, 28240 => 38042, 28241 => 38043, 28242 => 38044,
    1329     28243 => 38051, 28244 => 38052, 28245 => 38059, 28246 => 38058, 28247 => 38061,
    1330     28248 => 38060, 28249 => 38063, 28250 => 38064, 28251 => 38066, 28252 => 38068,
    1331     28253 => 38070, 28254 => 38071, 28255 => 38072, 28256 => 38073, 28257 => 38074,
    1332     28258 => 38076, 28259 => 38077, 28260 => 38079, 28261 => 38084, 28262 => 38088,
    1333     28263 => 38089, 28264 => 38090, 28265 => 38091, 28266 => 38092, 28267 => 38093,
    1334     28268 => 38094, 28269 => 38096, 28270 => 38097, 28271 => 38098, 28272 => 38101,
    1335     28273 => 38102, 28274 => 38103, 28275 => 38105, 28276 => 38104, 28277 => 38107,
    1336     28278 => 38110, 28279 => 38111, 28280 => 38112, 28281 => 38114, 28282 => 38116,
    1337     28283 => 38117, 28284 => 38119, 28285 => 38120, 28286 => 38122, 28449 => 38121,
    1338     28450 => 38123, 28451 => 38126, 28452 => 38127, 28453 => 38131, 28454 => 38132,
    1339     28455 => 38133, 28456 => 38135, 28457 => 38137, 28458 => 38140, 28459 => 38141,
    1340     28460 => 38143, 28461 => 38147, 28462 => 38146, 28463 => 38150, 28464 => 38151,
    1341     28465 => 38153, 28466 => 38154, 28467 => 38157, 28468 => 38158, 28469 => 38159,
    1342     28470 => 38162, 28471 => 38163, 28472 => 38164, 28473 => 38165, 28474 => 38166,
    1343     28475 => 38168, 28476 => 38171, 28477 => 38173, 28478 => 38174, 28479 => 38175,
    1344     28480 => 38178, 28481 => 38186, 28482 => 38187, 28483 => 38185, 28484 => 38188,
    1345     28485 => 38193, 28486 => 38194, 28487 => 38196, 28488 => 38198, 28489 => 38199,
    1346     28490 => 38200, 28491 => 38204, 28492 => 38206, 28493 => 38207, 28494 => 38210,
    1347     28495 => 38197, 28496 => 38212, 28497 => 38213, 28498 => 38214, 28499 => 38217,
    1348     28500 => 38220, 28501 => 38222, 28502 => 38223, 28503 => 38226, 28504 => 38227,
    1349     28505 => 38228, 28506 => 38230, 28507 => 38231, 28508 => 38232, 28509 => 38233,
    1350     28510 => 38235, 28511 => 38238, 28512 => 38239, 28513 => 38237, 28514 => 38241,
    1351     28515 => 38242, 28516 => 38244, 28517 => 38245, 28518 => 38246, 28519 => 38247,
    1352     28520 => 38248, 28521 => 38249, 28522 => 38250, 28523 => 38251, 28524 => 38252,
    1353     28525 => 38255, 28526 => 38257, 28527 => 38258, 28528 => 38259, 28529 => 38202,
    1354     28530 => 30695, 28531 => 30700, 28532 => 38601, 28533 => 31189, 28534 => 31213,
    1355     28535 => 31203, 28536 => 31211, 28537 => 31238, 28538 => 23879, 28539 => 31235,
    1356     28540 => 31234, 28541 => 31262, 28542 => 31252, 28705 => 31289, 28706 => 31287,
    1357     28707 => 31313, 28708 => 40655, 28709 => 39333, 28710 => 31344, 28711 => 30344,
    1358     28712 => 30350, 28713 => 30355, 28714 => 30361, 28715 => 30372, 28716 => 29918,
    1359     28717 => 29920, 28718 => 29996, 28719 => 40480, 28720 => 40482, 28721 => 40488,
    1360     28722 => 40489, 28723 => 40490, 28724 => 40491, 28725 => 40492, 28726 => 40498,
    1361     28727 => 40497, 28728 => 40502, 28729 => 40504, 28730 => 40503, 28731 => 40505,
    1362     28732 => 40506, 28733 => 40510, 28734 => 40513, 28735 => 40514, 28736 => 40516,
    1363     28737 => 40518, 28738 => 40519, 28739 => 40520, 28740 => 40521, 28741 => 40523,
    1364     28742 => 40524, 28743 => 40526, 28744 => 40529, 28745 => 40533, 28746 => 40535,
    1365     28747 => 40538, 28748 => 40539, 28749 => 40540, 28750 => 40542, 28751 => 40547,
    1366     28752 => 40550, 28753 => 40551, 28754 => 40552, 28755 => 40553, 28756 => 40554,
    1367     28757 => 40555, 28758 => 40556, 28759 => 40561, 28760 => 40557, 28761 => 40563,
    1368     28762 => 30098, 28763 => 30100, 28764 => 30102, 28765 => 30112, 28766 => 30109,
    1369     28767 => 30124, 28768 => 30115, 28769 => 30131, 28770 => 30132, 28771 => 30136,
    1370     28772 => 30148, 28773 => 30129, 28774 => 30128, 28775 => 30147, 28776 => 30146,
    1371     28777 => 30166, 28778 => 30157, 28779 => 30179, 28780 => 30184, 28781 => 30182,
    1372     28782 => 30180, 28783 => 30187, 28784 => 30183, 28785 => 30211, 28786 => 30193,
    1373     28787 => 30204, 28788 => 30207, 28789 => 30224, 28790 => 30208, 28791 => 30213,
    1374     28792 => 30220, 28793 => 30231, 28794 => 30218, 28795 => 30245, 28796 => 30232,
    1375     28797 => 30229, 28798 => 30233, 28961 => 30235, 28962 => 30268, 28963 => 30242,
    1376     28964 => 30240, 28965 => 30272, 28966 => 30253, 28967 => 30256, 28968 => 30271,
    1377     28969 => 30261, 28970 => 30275, 28971 => 30270, 28972 => 30259, 28973 => 30285,
    1378     28974 => 30302, 28975 => 30292, 28976 => 30300, 28977 => 30294, 28978 => 30315,
    1379     28979 => 30319, 28980 => 32714, 28981 => 31462, 28982 => 31352, 28983 => 31353,
    1380     28984 => 31360, 28985 => 31366, 28986 => 31368, 28987 => 31381, 28988 => 31398,
    1381     28989 => 31392, 28990 => 31404, 28991 => 31400, 28992 => 31405, 28993 => 31411,
    1382     28994 => 34916, 28995 => 34921, 28996 => 34930, 28997 => 34941, 28998 => 34943,
    1383     28999 => 34946, 29000 => 34978, 29001 => 35014, 29002 => 34999, 29003 => 35004,
    1384     29004 => 35017, 29005 => 35042, 29006 => 35022, 29007 => 35043, 29008 => 35045,
    1385     29009 => 35057, 29010 => 35098, 29011 => 35068, 29012 => 35048, 29013 => 35070,
    1386     29014 => 35056, 29015 => 35105, 29016 => 35097, 29017 => 35091, 29018 => 35099,
    1387     29019 => 35082, 29020 => 35124, 29021 => 35115, 29022 => 35126, 29023 => 35137,
    1388     29024 => 35174, 29025 => 35195, 29026 => 30091, 29027 => 32997, 29028 => 30386,
    1389     29029 => 30388, 29030 => 30684, 29031 => 32786, 29032 => 32788, 29033 => 32790,
    1390     29034 => 32796, 29035 => 32800, 29036 => 32802, 29037 => 32805, 29038 => 32806,
    1391     29039 => 32807, 29040 => 32809, 29041 => 32808, 29042 => 32817, 29043 => 32779,
    1392     29044 => 32821, 29045 => 32835, 29046 => 32838, 29047 => 32845, 29048 => 32850,
    1393     29049 => 32873, 29050 => 32881, 29051 => 35203, 29052 => 39032, 29053 => 39040,
    1394     29054 => 39043, 29217 => 39049, 29218 => 39052, 29219 => 39053, 29220 => 39055,
    1395     29221 => 39060, 29222 => 39066, 29223 => 39067, 29224 => 39070, 29225 => 39071,
    1396     29226 => 39073, 29227 => 39074, 29228 => 39077, 29229 => 39078, 29230 => 34381,
    1397     29231 => 34388, 29232 => 34412, 29233 => 34414, 29234 => 34431, 29235 => 34426,
    1398     29236 => 34428, 29237 => 34427, 29238 => 34472, 29239 => 34445, 29240 => 34443,
    1399     29241 => 34476, 29242 => 34461, 29243 => 34471, 29244 => 34467, 29245 => 34474,
    1400     29246 => 34451, 29247 => 34473, 29248 => 34486, 29249 => 34500, 29250 => 34485,
    1401     29251 => 34510, 29252 => 34480, 29253 => 34490, 29254 => 34481, 29255 => 34479,
    1402     29256 => 34505, 29257 => 34511, 29258 => 34484, 29259 => 34537, 29260 => 34545,
    1403     29261 => 34546, 29262 => 34541, 29263 => 34547, 29264 => 34512, 29265 => 34579,
    1404     29266 => 34526, 29267 => 34548, 29268 => 34527, 29269 => 34520, 29270 => 34513,
    1405     29271 => 34563, 29272 => 34567, 29273 => 34552, 29274 => 34568, 29275 => 34570,
    1406     29276 => 34573, 29277 => 34569, 29278 => 34595, 29279 => 34619, 29280 => 34590,
    1407     29281 => 34597, 29282 => 34606, 29283 => 34586, 29284 => 34622, 29285 => 34632,
    1408     29286 => 34612, 29287 => 34609, 29288 => 34601, 29289 => 34615, 29290 => 34623,
    1409     29291 => 34690, 29292 => 34594, 29293 => 34685, 29294 => 34686, 29295 => 34683,
    1410     29296 => 34656, 29297 => 34672, 29298 => 34636, 29299 => 34670, 29300 => 34699,
    1411     29301 => 34643, 29302 => 34659, 29303 => 34684, 29304 => 34660, 29305 => 34649,
    1412     29306 => 34661, 29307 => 34707, 29308 => 34735, 29309 => 34728, 29310 => 34770,
    1413     29473 => 34758, 29474 => 34696, 29475 => 34693, 29476 => 34733, 29477 => 34711,
    1414     29478 => 34691, 29479 => 34731, 29480 => 34789, 29481 => 34732, 29482 => 34741,
    1415     29483 => 34739, 29484 => 34763, 29485 => 34771, 29486 => 34749, 29487 => 34769,
    1416     29488 => 34752, 29489 => 34762, 29490 => 34779, 29491 => 34794, 29492 => 34784,
    1417     29493 => 34798, 29494 => 34838, 29495 => 34835, 29496 => 34814, 29497 => 34826,
    1418     29498 => 34843, 29499 => 34849, 29500 => 34873, 29501 => 34876, 29502 => 32566,
    1419     29503 => 32578, 29504 => 32580, 29505 => 32581, 29506 => 33296, 29507 => 31482,
    1420     29508 => 31485, 29509 => 31496, 29510 => 31491, 29511 => 31492, 29512 => 31509,
    1421     29513 => 31498, 29514 => 31531, 29515 => 31503, 29516 => 31559, 29517 => 31544,
    1422     29518 => 31530, 29519 => 31513, 29520 => 31534, 29521 => 31537, 29522 => 31520,
    1423     29523 => 31525, 29524 => 31524, 29525 => 31539, 29526 => 31550, 29527 => 31518,
    1424     29528 => 31576, 29529 => 31578, 29530 => 31557, 29531 => 31605, 29532 => 31564,
    1425     29533 => 31581, 29534 => 31584, 29535 => 31598, 29536 => 31611, 29537 => 31586,
    1426     29538 => 31602, 29539 => 31601, 29540 => 31632, 29541 => 31654, 29542 => 31655,
    1427     29543 => 31672, 29544 => 31660, 29545 => 31645, 29546 => 31656, 29547 => 31621,
    1428     29548 => 31658, 29549 => 31644, 29550 => 31650, 29551 => 31659, 29552 => 31668,
    1429     29553 => 31697, 29554 => 31681, 29555 => 31692, 29556 => 31709, 29557 => 31706,
    1430     29558 => 31717, 29559 => 31718, 29560 => 31722, 29561 => 31756, 29562 => 31742,
    1431     29563 => 31740, 29564 => 31759, 29565 => 31766, 29566 => 31755, 29729 => 31775,
    1432     29730 => 31786, 29731 => 31782, 29732 => 31800, 29733 => 31809, 29734 => 31808,
    1433     29735 => 33278, 29736 => 33281, 29737 => 33282, 29738 => 33284, 29739 => 33260,
    1434     29740 => 34884, 29741 => 33313, 29742 => 33314, 29743 => 33315, 29744 => 33325,
    1435     29745 => 33327, 29746 => 33320, 29747 => 33323, 29748 => 33336, 29749 => 33339,
    1436     29750 => 33331, 29751 => 33332, 29752 => 33342, 29753 => 33348, 29754 => 33353,
    1437     29755 => 33355, 29756 => 33359, 29757 => 33370, 29758 => 33375, 29759 => 33384,
    1438     29760 => 34942, 29761 => 34949, 29762 => 34952, 29763 => 35032, 29764 => 35039,
    1439     29765 => 35166, 29766 => 32669, 29767 => 32671, 29768 => 32679, 29769 => 32687,
    1440     29770 => 32688, 29771 => 32690, 29772 => 31868, 29773 => 25929, 29774 => 31889,
    1441     29775 => 31901, 29776 => 31900, 29777 => 31902, 29778 => 31906, 29779 => 31922,
    1442     29780 => 31932, 29781 => 31933, 29782 => 31937, 29783 => 31943, 29784 => 31948,
    1443     29785 => 31949, 29786 => 31944, 29787 => 31941, 29788 => 31959, 29789 => 31976,
    1444     29790 => 33390, 29791 => 26280, 29792 => 32703, 29793 => 32718, 29794 => 32725,
    1445     29795 => 32741, 29796 => 32737, 29797 => 32742, 29798 => 32745, 29799 => 32750,
    1446     29800 => 32755, 29801 => 31992, 29802 => 32119, 29803 => 32166, 29804 => 32174,
    1447     29805 => 32327, 29806 => 32411, 29807 => 40632, 29808 => 40628, 29809 => 36211,
    1448     29810 => 36228, 29811 => 36244, 29812 => 36241, 29813 => 36273, 29814 => 36199,
    1449     29815 => 36205, 29816 => 35911, 29817 => 35913, 29818 => 37194, 29819 => 37200,
    1450     29820 => 37198, 29821 => 37199, 29822 => 37220, 29985 => 37218, 29986 => 37217,
    1451     29987 => 37232, 29988 => 37225, 29989 => 37231, 29990 => 37245, 29991 => 37246,
    1452     29992 => 37234, 29993 => 37236, 29994 => 37241, 29995 => 37260, 29996 => 37253,
    1453     29997 => 37264, 29998 => 37261, 29999 => 37265, 30000 => 37282, 30001 => 37283,
    1454     30002 => 37290, 30003 => 37293, 30004 => 37294, 30005 => 37295, 30006 => 37301,
    1455     30007 => 37300, 30008 => 37306, 30009 => 35925, 30010 => 40574, 30011 => 36280,
    1456     30012 => 36331, 30013 => 36357, 30014 => 36441, 30015 => 36457, 30016 => 36277,
    1457     30017 => 36287, 30018 => 36284, 30019 => 36282, 30020 => 36292, 30021 => 36310,
    1458     30022 => 36311, 30023 => 36314, 30024 => 36318, 30025 => 36302, 30026 => 36303,
    1459     30027 => 36315, 30028 => 36294, 30029 => 36332, 30030 => 36343, 30031 => 36344,
    1460     30032 => 36323, 30033 => 36345, 30034 => 36347, 30035 => 36324, 30036 => 36361,
    1461     30037 => 36349, 30038 => 36372, 30039 => 36381, 30040 => 36383, 30041 => 36396,
    1462     30042 => 36398, 30043 => 36387, 30044 => 36399, 30045 => 36410, 30046 => 36416,
    1463     30047 => 36409, 30048 => 36405, 30049 => 36413, 30050 => 36401, 30051 => 36425,
    1464     30052 => 36417, 30053 => 36418, 30054 => 36433, 30055 => 36434, 30056 => 36426,
    1465     30057 => 36464, 30058 => 36470, 30059 => 36476, 30060 => 36463, 30061 => 36468,
    1466     30062 => 36485, 30063 => 36495, 30064 => 36500, 30065 => 36496, 30066 => 36508,
    1467     30067 => 36510, 30068 => 35960, 30069 => 35970, 30070 => 35978, 30071 => 35973,
    1468     30072 => 35992, 30073 => 35988, 30074 => 26011, 30075 => 35286, 30076 => 35294,
    1469     30077 => 35290, 30078 => 35292, 30241 => 35301, 30242 => 35307, 30243 => 35311,
    1470     30244 => 35390, 30245 => 35622, 30246 => 38739, 30247 => 38633, 30248 => 38643,
    1471     30249 => 38639, 30250 => 38662, 30251 => 38657, 30252 => 38664, 30253 => 38671,
    1472     30254 => 38670, 30255 => 38698, 30256 => 38701, 30257 => 38704, 30258 => 38718,
    1473     30259 => 40832, 30260 => 40835, 30261 => 40837, 30262 => 40838, 30263 => 40839,
    1474     30264 => 40840, 30265 => 40841, 30266 => 40842, 30267 => 40844, 30268 => 40702,
    1475     30269 => 40715, 30270 => 40717, 30271 => 38585, 30272 => 38588, 30273 => 38589,
    1476     30274 => 38606, 30275 => 38610, 30276 => 30655, 30277 => 38624, 30278 => 37518,
    1477     30279 => 37550, 30280 => 37576, 30281 => 37694, 30282 => 37738, 30283 => 37834,
    1478     30284 => 37775, 30285 => 37950, 30286 => 37995, 30287 => 40063, 30288 => 40066,
    1479     30289 => 40069, 30290 => 40070, 30291 => 40071, 30292 => 40072, 30293 => 31267,
    1480     30294 => 40075, 30295 => 40078, 30296 => 40080, 30297 => 40081, 30298 => 40082,
    1481     30299 => 40084, 30300 => 40085, 30301 => 40090, 30302 => 40091, 30303 => 40094,
    1482     30304 => 40095, 30305 => 40096, 30306 => 40097, 30307 => 40098, 30308 => 40099,
    1483     30309 => 40101, 30310 => 40102, 30311 => 40103, 30312 => 40104, 30313 => 40105,
    1484     30314 => 40107, 30315 => 40109, 30316 => 40110, 30317 => 40112, 30318 => 40113,
    1485     30319 => 40114, 30320 => 40115, 30321 => 40116, 30322 => 40117, 30323 => 40118,
    1486     30324 => 40119, 30325 => 40122, 30326 => 40123, 30327 => 40124, 30328 => 40125,
    1487     30329 => 40132, 30330 => 40133, 30331 => 40134, 30332 => 40135, 30333 => 40138,
    1488     30334 => 40139, 30497 => 40140, 30498 => 40141, 30499 => 40142, 30500 => 40143,
    1489     30501 => 40144, 30502 => 40147, 30503 => 40148, 30504 => 40149, 30505 => 40151,
    1490     30506 => 40152, 30507 => 40153, 30508 => 40156, 30509 => 40157, 30510 => 40159,
    1491     30511 => 40162, 30512 => 38780, 30513 => 38789, 30514 => 38801, 30515 => 38802,
    1492     30516 => 38804, 30517 => 38831, 30518 => 38827, 30519 => 38819, 30520 => 38834,
    1493     30521 => 38836, 30522 => 39601, 30523 => 39600, 30524 => 39607, 30525 => 40536,
    1494     30526 => 39606, 30527 => 39610, 30528 => 39612, 30529 => 39617, 30530 => 39616,
    1495     30531 => 39621, 30532 => 39618, 30533 => 39627, 30534 => 39628, 30535 => 39633,
    1496     30536 => 39749, 30537 => 39747, 30538 => 39751, 30539 => 39753, 30540 => 39752,
    1497     30541 => 39757, 30542 => 39761, 30543 => 39144, 30544 => 39181, 30545 => 39214,
    1498     30546 => 39253, 30547 => 39252, 30548 => 39647, 30549 => 39649, 30550 => 39654,
    1499     30551 => 39663, 30552 => 39659, 30553 => 39675, 30554 => 39661, 30555 => 39673,
    1500     30556 => 39688, 30557 => 39695, 30558 => 39699, 30559 => 39711, 30560 => 39715,
    1501     30561 => 40637, 30562 => 40638, 30563 => 32315, 30564 => 40578, 30565 => 40583,
    1502     30566 => 40584, 30567 => 40587, 30568 => 40594, 30569 => 37846, 30570 => 40605,
    1503     30571 => 40607, 30572 => 40667, 30573 => 40668, 30574 => 40669, 30575 => 40672,
    1504     30576 => 40671, 30577 => 40674, 30578 => 40681, 30579 => 40679, 30580 => 40677,
    1505     30581 => 40682, 30582 => 40687, 30583 => 40738, 30584 => 40748, 30585 => 40751,
    1506     30586 => 40761, 30587 => 40759, 30588 => 40765, 30589 => 40766, 30590 => 40772,
    1507     0 => 0 );
     13// --------------------------------------------------------------------
     14// This code table is used to translate GB2312 code (key) to
     15// it's corresponding Unicode value (data)
     16// --------------------------------------------------------------------
     17    private $codetable = array( 
     18        8481 => 12288, 8482 => 12289, 8483 => 12290, 8484 => 12539, 8485 => 713,
     19        8486 => 711, 8487 => 168, 8488 => 12291, 8489 => 12293, 8490 => 8213,
     20        8491 => 65374, 8492 => 8214, 8493 => 8230, 8494 => 8216, 8495 => 8217,
     21        8496 => 8220, 8497 => 8221, 8498 => 12308, 8499 => 12309, 8500 => 12296,
     22        8501 => 12297, 8502 => 12298, 8503 => 12299, 8504 => 12300, 8505 => 12301,
     23        8506 => 12302, 8507 => 12303, 8508 => 12310, 8509 => 12311, 8510 => 12304,
     24        8511 => 12305, 8512 => 177, 8513 => 215, 8514 => 247, 8515 => 8758,
     25        8516 => 8743, 8517 => 8744, 8518 => 8721, 8519 => 8719, 8520 => 8746,
     26        8521 => 8745, 8522 => 8712, 8523 => 8759, 8524 => 8730, 8525 => 8869,
     27        8526 => 8741, 8527 => 8736, 8528 => 8978, 8529 => 8857, 8530 => 8747,
     28        8531 => 8750, 8532 => 8801, 8533 => 8780, 8534 => 8776, 8535 => 8765,
     29        8536 => 8733, 8537 => 8800, 8538 => 8814, 8539 => 8815, 8540 => 8804,
     30        8541 => 8805, 8542 => 8734, 8543 => 8757, 8544 => 8756, 8545 => 9794,
     31        8546 => 9792, 8547 => 176, 8548 => 8242, 8549 => 8243, 8550 => 8451,
     32        8551 => 65284, 8552 => 164, 8553 => 65504, 8554 => 65505, 8555 => 8240,
     33        8556 => 167, 8557 => 8470, 8558 => 9734, 8559 => 9733, 8560 => 9675,
     34        8561 => 9679, 8562 => 9678, 8563 => 9671, 8564 => 9670, 8565 => 9633,
     35        8566 => 9632, 8567 => 9651, 8568 => 9650, 8569 => 8251, 8570 => 8594,
     36        8571 => 8592, 8572 => 8593, 8573 => 8595, 8574 => 12307, 8753 => 9352,
     37        8754 => 9353, 8755 => 9354, 8756 => 9355, 8757 => 9356, 8758 => 9357,
     38        8759 => 9358, 8760 => 9359, 8761 => 9360, 8762 => 9361, 8763 => 9362,
     39        8764 => 9363, 8765 => 9364, 8766 => 9365, 8767 => 9366, 8768 => 9367,
     40        8769 => 9368, 8770 => 9369, 8771 => 9370, 8772 => 9371, 8773 => 9332,
     41        8774 => 9333, 8775 => 9334, 8776 => 9335, 8777 => 9336, 8778 => 9337,
     42        8779 => 9338, 8780 => 9339, 8781 => 9340, 8782 => 9341, 8783 => 9342,
     43        8784 => 9343, 8785 => 9344, 8786 => 9345, 8787 => 9346, 8788 => 9347,
     44        8789 => 9348, 8790 => 9349, 8791 => 9350, 8792 => 9351, 8793 => 9312,
     45        8794 => 9313, 8795 => 9314, 8796 => 9315, 8797 => 9316, 8798 => 9317,
     46        8799 => 9318, 8800 => 9319, 8801 => 9320, 8802 => 9321, 8805 => 12832,
     47        8806 => 12833, 8807 => 12834, 8808 => 12835, 8809 => 12836, 8810 => 12837,
     48        8811 => 12838, 8812 => 12839, 8813 => 12840, 8814 => 12841, 8817 => 8544,
     49        8818 => 8545, 8819 => 8546, 8820 => 8547, 8821 => 8548, 8822 => 8549,
     50        8823 => 8550, 8824 => 8551, 8825 => 8552, 8826 => 8553, 8827 => 8554,
     51        8828 => 8555, 8993 => 65281, 8994 => 65282, 8995 => 65283, 8996 => 65509,
     52        8997 => 65285, 8998 => 65286, 8999 => 65287, 9000 => 65288, 9001 => 65289,
     53        9002 => 65290, 9003 => 65291, 9004 => 65292, 9005 => 65293, 9006 => 65294,
     54        9007 => 65295, 9008 => 65296, 9009 => 65297, 9010 => 65298, 9011 => 65299,
     55        9012 => 65300, 9013 => 65301, 9014 => 65302, 9015 => 65303, 9016 => 65304,
     56        9017 => 65305, 9018 => 65306, 9019 => 65307, 9020 => 65308, 9021 => 65309,
     57        9022 => 65310, 9023 => 65311, 9024 => 65312, 9025 => 65313, 9026 => 65314,
     58        9027 => 65315, 9028 => 65316, 9029 => 65317, 9030 => 65318, 9031 => 65319,
     59        9032 => 65320, 9033 => 65321, 9034 => 65322, 9035 => 65323, 9036 => 65324,
     60        9037 => 65325, 9038 => 65326, 9039 => 65327, 9040 => 65328, 9041 => 65329,
     61        9042 => 65330, 9043 => 65331, 9044 => 65332, 9045 => 65333, 9046 => 65334,
     62        9047 => 65335, 9048 => 65336, 9049 => 65337, 9050 => 65338, 9051 => 65339,
     63        9052 => 65340, 9053 => 65341, 9054 => 65342, 9055 => 65343, 9056 => 65344,
     64        9057 => 65345, 9058 => 65346, 9059 => 65347, 9060 => 65348, 9061 => 65349,
     65        9062 => 65350, 9063 => 65351, 9064 => 65352, 9065 => 65353, 9066 => 65354,
     66        9067 => 65355, 9068 => 65356, 9069 => 65357, 9070 => 65358, 9071 => 65359,
     67        9072 => 65360, 9073 => 65361, 9074 => 65362, 9075 => 65363, 9076 => 65364,
     68        9077 => 65365, 9078 => 65366, 9079 => 65367, 9080 => 65368, 9081 => 65369,
     69        9082 => 65370, 9083 => 65371, 9084 => 65372, 9085 => 65373, 9086 => 65507,
     70        9249 => 12353, 9250 => 12354, 9251 => 12355, 9252 => 12356, 9253 => 12357,
     71        9254 => 12358, 9255 => 12359, 9256 => 12360, 9257 => 12361, 9258 => 12362,
     72        9259 => 12363, 9260 => 12364, 9261 => 12365, 9262 => 12366, 9263 => 12367,
     73        9264 => 12368, 9265 => 12369, 9266 => 12370, 9267 => 12371, 9268 => 12372,
     74        9269 => 12373, 9270 => 12374, 9271 => 12375, 9272 => 12376, 9273 => 12377,
     75        9274 => 12378, 9275 => 12379, 9276 => 12380, 9277 => 12381, 9278 => 12382,
     76        9279 => 12383, 9280 => 12384, 9281 => 12385, 9282 => 12386, 9283 => 12387,
     77        9284 => 12388, 9285 => 12389, 9286 => 12390, 9287 => 12391, 9288 => 12392,
     78        9289 => 12393, 9290 => 12394, 9291 => 12395, 9292 => 12396, 9293 => 12397,
     79        9294 => 12398, 9295 => 12399, 9296 => 12400, 9297 => 12401, 9298 => 12402,
     80        9299 => 12403, 9300 => 12404, 9301 => 12405, 9302 => 12406, 9303 => 12407,
     81        9304 => 12408, 9305 => 12409, 9306 => 12410, 9307 => 12411, 9308 => 12412,
     82        9309 => 12413, 9310 => 12414, 9311 => 12415, 9312 => 12416, 9313 => 12417,
     83        9314 => 12418, 9315 => 12419, 9316 => 12420, 9317 => 12421, 9318 => 12422,
     84        9319 => 12423, 9320 => 12424, 9321 => 12425, 9322 => 12426, 9323 => 12427,
     85        9324 => 12428, 9325 => 12429, 9326 => 12430, 9327 => 12431, 9328 => 12432,
     86        9329 => 12433, 9330 => 12434, 9331 => 12435, 9505 => 12449, 9506 => 12450,
     87        9507 => 12451, 9508 => 12452, 9509 => 12453, 9510 => 12454, 9511 => 12455,
     88        9512 => 12456, 9513 => 12457, 9514 => 12458, 9515 => 12459, 9516 => 12460,
     89        9517 => 12461, 9518 => 12462, 9519 => 12463, 9520 => 12464, 9521 => 12465,
     90        9522 => 12466, 9523 => 12467, 9524 => 12468, 9525 => 12469, 9526 => 12470,
     91        9527 => 12471, 9528 => 12472, 9529 => 12473, 9530 => 12474, 9531 => 12475,
     92        9532 => 12476, 9533 => 12477, 9534 => 12478, 9535 => 12479, 9536 => 12480,
     93        9537 => 12481, 9538 => 12482, 9539 => 12483, 9540 => 12484, 9541 => 12485,
     94        9542 => 12486, 9543 => 12487, 9544 => 12488, 9545 => 12489, 9546 => 12490,
     95        9547 => 12491, 9548 => 12492, 9549 => 12493, 9550 => 12494, 9551 => 12495,
     96        9552 => 12496, 9553 => 12497, 9554 => 12498, 9555 => 12499, 9556 => 12500,
     97        9557 => 12501, 9558 => 12502, 9559 => 12503, 9560 => 12504, 9561 => 12505,
     98        9562 => 12506, 9563 => 12507, 9564 => 12508, 9565 => 12509, 9566 => 12510,
     99        9567 => 12511, 9568 => 12512, 9569 => 12513, 9570 => 12514, 9571 => 12515,
     100        9572 => 12516, 9573 => 12517, 9574 => 12518, 9575 => 12519, 9576 => 12520,
     101        9577 => 12521, 9578 => 12522, 9579 => 12523, 9580 => 12524, 9581 => 12525,
     102        9582 => 12526, 9583 => 12527, 9584 => 12528, 9585 => 12529, 9586 => 12530,
     103        9587 => 12531, 9588 => 12532, 9589 => 12533, 9590 => 12534, 9761 => 913,
     104        9762 => 914, 9763 => 915, 9764 => 916, 9765 => 917, 9766 => 918,
     105        9767 => 919, 9768 => 920, 9769 => 921, 9770 => 922, 9771 => 923,
     106        9772 => 924, 9773 => 925, 9774 => 926, 9775 => 927, 9776 => 928,
     107        9777 => 929, 9778 => 931, 9779 => 932, 9780 => 933, 9781 => 934,
     108        9782 => 935, 9783 => 936, 9784 => 937, 9793 => 945, 9794 => 946,
     109        9795 => 947, 9796 => 948, 9797 => 949, 9798 => 950, 9799 => 951,
     110        9800 => 952, 9801 => 953, 9802 => 954, 9803 => 955, 9804 => 956,
     111        9805 => 957, 9806 => 958, 9807 => 959, 9808 => 960, 9809 => 961,
     112        9810 => 963, 9811 => 964, 9812 => 965, 9813 => 966, 9814 => 967,
     113        9815 => 968, 9816 => 969, 10017 => 1040, 10018 => 1041, 10019 => 1042,
     114        10020 => 1043, 10021 => 1044, 10022 => 1045, 10023 => 1025, 10024 => 1046,
     115        10025 => 1047, 10026 => 1048, 10027 => 1049, 10028 => 1050, 10029 => 1051,
     116        10030 => 1052, 10031 => 1053, 10032 => 1054, 10033 => 1055, 10034 => 1056,
     117        10035 => 1057, 10036 => 1058, 10037 => 1059, 10038 => 1060, 10039 => 1061,
     118        10040 => 1062, 10041 => 1063, 10042 => 1064, 10043 => 1065, 10044 => 1066,
     119        10045 => 1067, 10046 => 1068, 10047 => 1069, 10048 => 1070, 10049 => 1071,
     120        10065 => 1072, 10066 => 1073, 10067 => 1074, 10068 => 1075, 10069 => 1076,
     121        10070 => 1077, 10071 => 1105, 10072 => 1078, 10073 => 1079, 10074 => 1080,
     122        10075 => 1081, 10076 => 1082, 10077 => 1083, 10078 => 1084, 10079 => 1085,
     123        10080 => 1086, 10081 => 1087, 10082 => 1088, 10083 => 1089, 10084 => 1090,
     124        10085 => 1091, 10086 => 1092, 10087 => 1093, 10088 => 1094, 10089 => 1095,
     125        10090 => 1096, 10091 => 1097, 10092 => 1098, 10093 => 1099, 10094 => 1100,
     126        10095 => 1101, 10096 => 1102, 10097 => 1103, 10273 => 257, 10274 => 225,
     127        10275 => 462, 10276 => 224, 10277 => 275, 10278 => 233, 10279 => 283,
     128        10280 => 232, 10281 => 299, 10282 => 237, 10283 => 464, 10284 => 236,
     129        10285 => 333, 10286 => 243, 10287 => 466, 10288 => 242, 10289 => 363,
     130        10290 => 250, 10291 => 468, 10292 => 249, 10293 => 470, 10294 => 472,
     131        10295 => 474, 10296 => 476, 10297 => 252, 10298 => 234, 10309 => 12549,
     132        10310 => 12550, 10311 => 12551, 10312 => 12552, 10313 => 12553, 10314 => 12554,
     133        10315 => 12555, 10316 => 12556, 10317 => 12557, 10318 => 12558, 10319 => 12559,
     134        10320 => 12560, 10321 => 12561, 10322 => 12562, 10323 => 12563, 10324 => 12564,
     135        10325 => 12565, 10326 => 12566, 10327 => 12567, 10328 => 12568, 10329 => 12569,
     136        10330 => 12570, 10331 => 12571, 10332 => 12572, 10333 => 12573, 10334 => 12574,
     137        10335 => 12575, 10336 => 12576, 10337 => 12577, 10338 => 12578, 10339 => 12579,
     138        10340 => 12580, 10341 => 12581, 10342 => 12582, 10343 => 12583, 10344 => 12584,
     139        10345 => 12585, 10532 => 9472, 10533 => 9473, 10534 => 9474, 10535 => 9475,
     140        10536 => 9476, 10537 => 9477, 10538 => 9478, 10539 => 9479, 10540 => 9480,
     141        10541 => 9481, 10542 => 9482, 10543 => 9483, 10544 => 9484, 10545 => 9485,
     142        10546 => 9486, 10547 => 9487, 10548 => 9488, 10549 => 9489, 10550 => 9490,
     143        10551 => 9491, 10552 => 9492, 10553 => 9493, 10554 => 9494, 10555 => 9495,
     144        10556 => 9496, 10557 => 9497, 10558 => 9498, 10559 => 9499, 10560 => 9500,
     145        10561 => 9501, 10562 => 9502, 10563 => 9503, 10564 => 9504, 10565 => 9505,
     146        10566 => 9506, 10567 => 9507, 10568 => 9508, 10569 => 9509, 10570 => 9510,
     147        10571 => 9511, 10572 => 9512, 10573 => 9513, 10574 => 9514, 10575 => 9515,
     148        10576 => 9516, 10577 => 9517, 10578 => 9518, 10579 => 9519, 10580 => 9520,
     149        10581 => 9521, 10582 => 9522, 10583 => 9523, 10584 => 9524, 10585 => 9525,
     150        10586 => 9526, 10587 => 9527, 10588 => 9528, 10589 => 9529, 10590 => 9530,
     151        10591 => 9531, 10592 => 9532, 10593 => 9533, 10594 => 9534, 10595 => 9535,
     152        10596 => 9536, 10597 => 9537, 10598 => 9538, 10599 => 9539, 10600 => 9540,
     153        10601 => 9541, 10602 => 9542, 10603 => 9543, 10604 => 9544, 10605 => 9545,
     154        10606 => 9546, 10607 => 9547, 12321 => 21834, 12322 => 38463, 12323 => 22467,
     155        12324 => 25384, 12325 => 21710, 12326 => 21769, 12327 => 21696, 12328 => 30353,
     156        12329 => 30284, 12330 => 34108, 12331 => 30702, 12332 => 33406, 12333 => 30861,
     157        12334 => 29233, 12335 => 38552, 12336 => 38797, 12337 => 27688, 12338 => 23433,
     158        12339 => 20474, 12340 => 25353, 12341 => 26263, 12342 => 23736, 12343 => 33018,
     159        12344 => 26696, 12345 => 32942, 12346 => 26114, 12347 => 30414, 12348 => 20985,
     160        12349 => 25942, 12350 => 29100, 12351 => 32753, 12352 => 34948, 12353 => 20658,
     161        12354 => 22885, 12355 => 25034, 12356 => 28595, 12357 => 33453, 12358 => 25420,
     162        12359 => 25170, 12360 => 21485, 12361 => 21543, 12362 => 31494, 12363 => 20843,
     163        12364 => 30116, 12365 => 24052, 12366 => 25300, 12367 => 36299, 12368 => 38774,
     164        12369 => 25226, 12370 => 32793, 12371 => 22365, 12372 => 38712, 12373 => 32610,
     165        12374 => 29240, 12375 => 30333, 12376 => 26575, 12377 => 30334, 12378 => 25670,
     166        12379 => 20336, 12380 => 36133, 12381 => 25308, 12382 => 31255, 12383 => 26001,
     167        12384 => 29677, 12385 => 25644, 12386 => 25203, 12387 => 33324, 12388 => 39041,
     168        12389 => 26495, 12390 => 29256, 12391 => 25198, 12392 => 25292, 12393 => 20276,
     169        12394 => 29923, 12395 => 21322, 12396 => 21150, 12397 => 32458, 12398 => 37030,
     170        12399 => 24110, 12400 => 26758, 12401 => 27036, 12402 => 33152, 12403 => 32465,
     171        12404 => 26834, 12405 => 30917, 12406 => 34444, 12407 => 38225, 12408 => 20621,
     172        12409 => 35876, 12410 => 33502, 12411 => 32990, 12412 => 21253, 12413 => 35090,
     173        12414 => 21093, 12577 => 34180, 12578 => 38649, 12579 => 20445, 12580 => 22561,
     174        12581 => 39281, 12582 => 23453, 12583 => 25265, 12584 => 25253, 12585 => 26292,
     175        12586 => 35961, 12587 => 40077, 12588 => 29190, 12589 => 26479, 12590 => 30865,
     176        12591 => 24754, 12592 => 21329, 12593 => 21271, 12594 => 36744, 12595 => 32972,
     177        12596 => 36125, 12597 => 38049, 12598 => 20493, 12599 => 29384, 12600 => 22791,
     178        12601 => 24811, 12602 => 28953, 12603 => 34987, 12604 => 22868, 12605 => 33519,
     179        12606 => 26412, 12607 => 31528, 12608 => 23849, 12609 => 32503, 12610 => 29997,
     180        12611 => 27893, 12612 => 36454, 12613 => 36856, 12614 => 36924, 12615 => 40763,
     181        12616 => 27604, 12617 => 37145, 12618 => 31508, 12619 => 24444, 12620 => 30887,
     182        12621 => 34006, 12622 => 34109, 12623 => 27605, 12624 => 27609, 12625 => 27606,
     183        12626 => 24065, 12627 => 24199, 12628 => 30201, 12629 => 38381, 12630 => 25949,
     184        12631 => 24330, 12632 => 24517, 12633 => 36767, 12634 => 22721, 12635 => 33218,
     185        12636 => 36991, 12637 => 38491, 12638 => 38829, 12639 => 36793, 12640 => 32534,
     186        12641 => 36140, 12642 => 25153, 12643 => 20415, 12644 => 21464, 12645 => 21342,
     187        12646 => 36776, 12647 => 36777, 12648 => 36779, 12649 => 36941, 12650 => 26631,
     188        12651 => 24426, 12652 => 33176, 12653 => 34920, 12654 => 40150, 12655 => 24971,
     189        12656 => 21035, 12657 => 30250, 12658 => 24428, 12659 => 25996, 12660 => 28626,
     190        12661 => 28392, 12662 => 23486, 12663 => 25672, 12664 => 20853, 12665 => 20912,
     191        12666 => 26564, 12667 => 19993, 12668 => 31177, 12669 => 39292, 12670 => 28851,
     192        12833 => 30149, 12834 => 24182, 12835 => 29627, 12836 => 33760, 12837 => 25773,
     193        12838 => 25320, 12839 => 38069, 12840 => 27874, 12841 => 21338, 12842 => 21187,
     194        12843 => 25615, 12844 => 38082, 12845 => 31636, 12846 => 20271, 12847 => 24091,
     195        12848 => 33334, 12849 => 33046, 12850 => 33162, 12851 => 28196, 12852 => 27850,
     196        12853 => 39539, 12854 => 25429, 12855 => 21340, 12856 => 21754, 12857 => 34917,
     197        12858 => 22496, 12859 => 19981, 12860 => 24067, 12861 => 27493, 12862 => 31807,
     198        12863 => 37096, 12864 => 24598, 12865 => 25830, 12866 => 29468, 12867 => 35009,
     199        12868 => 26448, 12869 => 25165, 12870 => 36130, 12871 => 30572, 12872 => 36393,
     200        12873 => 37319, 12874 => 24425, 12875 => 33756, 12876 => 34081, 12877 => 39184,
     201        12878 => 21442, 12879 => 34453, 12880 => 27531, 12881 => 24813, 12882 => 24808,
     202        12883 => 28799, 12884 => 33485, 12885 => 33329, 12886 => 20179, 12887 => 27815,
     203        12888 => 34255, 12889 => 25805, 12890 => 31961, 12891 => 27133, 12892 => 26361,
     204        12893 => 33609, 12894 => 21397, 12895 => 31574, 12896 => 20391, 12897 => 20876,
     205        12898 => 27979, 12899 => 23618, 12900 => 36461, 12901 => 25554, 12902 => 21449,
     206        12903 => 33580, 12904 => 33590, 12905 => 26597, 12906 => 30900, 12907 => 25661,
     207        12908 => 23519, 12909 => 23700, 12910 => 24046, 12911 => 35815, 12912 => 25286,
     208        12913 => 26612, 12914 => 35962, 12915 => 25600, 12916 => 25530, 12917 => 34633,
     209        12918 => 39307, 12919 => 35863, 12920 => 32544, 12921 => 38130, 12922 => 20135,
     210        12923 => 38416, 12924 => 39076, 12925 => 26124, 12926 => 29462, 13089 => 22330,
     211        13090 => 23581, 13091 => 24120, 13092 => 38271, 13093 => 20607, 13094 => 32928,
     212        13095 => 21378, 13096 => 25950, 13097 => 30021, 13098 => 21809, 13099 => 20513,
     213        13100 => 36229, 13101 => 25220, 13102 => 38046, 13103 => 26397, 13104 => 22066,
     214        13105 => 28526, 13106 => 24034, 13107 => 21557, 13108 => 28818, 13109 => 36710,
     215        13110 => 25199, 13111 => 25764, 13112 => 25507, 13113 => 24443, 13114 => 28552,
     216        13115 => 37108, 13116 => 33251, 13117 => 36784, 13118 => 23576, 13119 => 26216,
     217        13120 => 24561, 13121 => 27785, 13122 => 38472, 13123 => 36225, 13124 => 34924,
     218        13125 => 25745, 13126 => 31216, 13127 => 22478, 13128 => 27225, 13129 => 25104,
     219        13130 => 21576, 13131 => 20056, 13132 => 31243, 13133 => 24809, 13134 => 28548,
     220        13135 => 35802, 13136 => 25215, 13137 => 36894, 13138 => 39563, 13139 => 31204,
     22113140 => 21507, 13141 => 30196, 13142 => 25345, 13143 => 21273, 13144 => 27744,
     22213145 => 36831, 13146 => 24347, 13147 => 39536, 13148 => 32827, 13149 => 40831,
     22313150 => 20360, 13151 => 23610, 13152 => 36196, 13153 => 32709, 13154 => 26021,
     22413155 => 28861, 13156 => 20805, 13157 => 20914, 13158 => 34411, 13159 => 23815,
     22513160 => 23456, 13161 => 25277, 13162 => 37228, 13163 => 30068, 13164 => 36364,
     22613165 => 31264, 13166 => 24833, 13167 => 31609, 13168 => 20167, 13169 => 32504,
     22713170 => 30597, 13171 => 19985, 13172 => 33261, 13173 => 21021, 13174 => 20986,
     22813175 => 27249, 13176 => 21416, 13177 => 36487, 13178 => 38148, 13179 => 38607,
     22913180 => 28353, 13181 => 38500, 13182 => 26970, 13345 => 30784, 13346 => 20648,
     23013347 => 30679, 13348 => 25616, 13349 => 35302, 13350 => 22788, 13351 => 25571,
     23113352 => 24029, 13353 => 31359, 13354 => 26941, 13355 => 20256, 13356 => 33337,
     23213357 => 21912, 13358 => 20018, 13359 => 30126, 13360 => 31383, 13361 => 24162,
     23313362 => 24202, 13363 => 38383, 13364 => 21019, 13365 => 21561, 13366 => 28810,
     23413367 => 25462, 13368 => 38180, 13369 => 22402, 13370 => 26149, 13371 => 26943,
     23513372 => 37255, 13373 => 21767, 13374 => 28147, 13375 => 32431, 13376 => 34850,
     23613377 => 25139, 13378 => 32496, 13379 => 30133, 13380 => 33576, 13381 => 30913,
     23713382 => 38604, 13383 => 36766, 13384 => 24904, 13385 => 29943, 13386 => 35789,
     23813387 => 27492, 13388 => 21050, 13389 => 36176, 13390 => 27425, 13391 => 32874,
     23913392 => 33905, 13393 => 22257, 13394 => 21254, 13395 => 20174, 13396 => 19995,
     24013397 => 20945, 13398 => 31895, 13399 => 37259, 13400 => 31751, 13401 => 20419,
     24113402 => 36479, 13403 => 31713, 13404 => 31388, 13405 => 25703, 13406 => 23828,
     24213407 => 20652, 13408 => 33030, 13409 => 30209, 13410 => 31929, 13411 => 28140,
     24313412 => 32736, 13413 => 26449, 13414 => 23384, 13415 => 23544, 13416 => 30923,
     24413417 => 25774, 13418 => 25619, 13419 => 25514, 13420 => 25387, 13421 => 38169,
     24513422 => 25645, 13423 => 36798, 13424 => 31572, 13425 => 30249, 13426 => 25171,
     24613427 => 22823, 13428 => 21574, 13429 => 27513, 13430 => 20643, 13431 => 25140,
     24713432 => 24102, 13433 => 27526, 13434 => 20195, 13435 => 36151, 13436 => 34955,
     24813437 => 24453, 13438 => 36910, 13601 => 24608, 13602 => 32829, 13603 => 25285,
     24913604 => 20025, 13605 => 21333, 13606 => 37112, 13607 => 25528, 13608 => 32966,
     25013609 => 26086, 13610 => 27694, 13611 => 20294, 13612 => 24814, 13613 => 28129,
     25113614 => 35806, 13615 => 24377, 13616 => 34507, 13617 => 24403, 13618 => 25377,
     25213619 => 20826, 13620 => 33633, 13621 => 26723, 13622 => 20992, 13623 => 25443,
     25313624 => 36424, 13625 => 20498, 13626 => 23707, 13627 => 31095, 13628 => 23548,
     25413629 => 21040, 13630 => 31291, 13631 => 24764, 13632 => 36947, 13633 => 30423,
     25513634 => 24503, 13635 => 24471, 13636 => 30340, 13637 => 36460, 13638 => 28783,
     25613639 => 30331, 13640 => 31561, 13641 => 30634, 13642 => 20979, 13643 => 37011,
     25713644 => 22564, 13645 => 20302, 13646 => 28404, 13647 => 36842, 13648 => 25932,
     25813649 => 31515, 13650 => 29380, 13651 => 28068, 13652 => 32735, 13653 => 23265,
     25913654 => 25269, 13655 => 24213, 13656 => 22320, 13657 => 33922, 13658 => 31532,
     26013659 => 24093, 13660 => 24351, 13661 => 36882, 13662 => 32532, 13663 => 39072,
     26113664 => 25474, 13665 => 28359, 13666 => 30872, 13667 => 28857, 13668 => 20856,
     26213669 => 38747, 13670 => 22443, 13671 => 30005, 13672 => 20291, 13673 => 30008,
     26313674 => 24215, 13675 => 24806, 13676 => 22880, 13677 => 28096, 13678 => 27583,
     26413679 => 30857, 13680 => 21500, 13681 => 38613, 13682 => 20939, 13683 => 20993,
     26513684 => 25481, 13685 => 21514, 13686 => 38035, 13687 => 35843, 13688 => 36300,
     26613689 => 29241, 13690 => 30879, 13691 => 34678, 13692 => 36845, 13693 => 35853,
     26713694 => 21472, 13857 => 19969, 13858 => 30447, 13859 => 21486, 13860 => 38025,
     26813861 => 39030, 13862 => 40718, 13863 => 38189, 13864 => 23450, 13865 => 35746,
     26913866 => 20002, 13867 => 19996, 13868 => 20908, 13869 => 33891, 13870 => 25026,
     27013871 => 21160, 13872 => 26635, 13873 => 20375, 13874 => 24683, 13875 => 20923,
     27113876 => 27934, 13877 => 20828, 13878 => 25238, 13879 => 26007, 13880 => 38497,
     27213881 => 35910, 13882 => 36887, 13883 => 30168, 13884 => 37117, 13885 => 30563,
     27313886 => 27602, 13887 => 29322, 13888 => 29420, 13889 => 35835, 13890 => 22581,
     27413891 => 30585, 13892 => 36172, 13893 => 26460, 13894 => 38208, 13895 => 32922,
     27513896 => 24230, 13897 => 28193, 13898 => 22930, 13899 => 31471, 13900 => 30701,
     27613901 => 38203, 13902 => 27573, 13903 => 26029, 13904 => 32526, 13905 => 22534,
     27713906 => 20817, 13907 => 38431, 13908 => 23545, 13909 => 22697, 13910 => 21544,
     27813911 => 36466, 13912 => 25958, 13913 => 39039, 13914 => 22244, 13915 => 38045,
     27913916 => 30462, 13917 => 36929, 13918 => 25479, 13919 => 21702, 13920 => 22810,
     28013921 => 22842, 13922 => 22427, 13923 => 36530, 13924 => 26421, 13925 => 36346,
     28113926 => 33333, 13927 => 21057, 13928 => 24816, 13929 => 22549, 13930 => 34558,
     28213931 => 23784, 13932 => 40517, 13933 => 20420, 13934 => 39069, 13935 => 35769,
     28313936 => 23077, 13937 => 24694, 13938 => 21380, 13939 => 25212, 13940 => 36943,
     28413941 => 37122, 13942 => 39295, 13943 => 24681, 13944 => 32780, 13945 => 20799,
     28513946 => 32819, 13947 => 23572, 13948 => 39285, 13949 => 27953, 13950 => 20108,
     28614113 => 36144, 14114 => 21457, 14115 => 32602, 14116 => 31567, 14117 => 20240,
     28714118 => 20047, 14119 => 38400, 14120 => 27861, 14121 => 29648, 14122 => 34281,
     28814123 => 24070, 14124 => 30058, 14125 => 32763, 14126 => 27146, 14127 => 30718,
     28914128 => 38034, 14129 => 32321, 14130 => 20961, 14131 => 28902, 14132 => 21453,
     29014133 => 36820, 14134 => 33539, 14135 => 36137, 14136 => 29359, 14137 => 39277,
     29114138 => 27867, 14139 => 22346, 14140 => 33459, 14141 => 26041, 14142 => 32938,
     29214143 => 25151, 14144 => 38450, 14145 => 22952, 14146 => 20223, 14147 => 35775,
     29314148 => 32442, 14149 => 25918, 14150 => 33778, 14151 => 38750, 14152 => 21857,
     29414153 => 39134, 14154 => 32933, 14155 => 21290, 14156 => 35837, 14157 => 21536,
     29514158 => 32954, 14159 => 24223, 14160 => 27832, 14161 => 36153, 14162 => 33452,
     29614163 => 37210, 14164 => 21545, 14165 => 27675, 14166 => 20998, 14167 => 32439,
     29714168 => 22367, 14169 => 28954, 14170 => 27774, 14171 => 31881, 14172 => 22859,
     29814173 => 20221, 14174 => 24575, 14175 => 24868, 14176 => 31914, 14177 => 20016,
     29914178 => 23553, 14179 => 26539, 14180 => 34562, 14181 => 23792, 14182 => 38155,
     30014183 => 39118, 14184 => 30127, 14185 => 28925, 14186 => 36898, 14187 => 20911,
     30114188 => 32541, 14189 => 35773, 14190 => 22857, 14191 => 20964, 14192 => 20315,
     30214193 => 21542, 14194 => 22827, 14195 => 25975, 14196 => 32932, 14197 => 23413,
     30314198 => 25206, 14199 => 25282, 14200 => 36752, 14201 => 24133, 14202 => 27679,
     30414203 => 31526, 14204 => 20239, 14205 => 20440, 14206 => 26381, 14369 => 28014,
     30514370 => 28074, 14371 => 31119, 14372 => 34993, 14373 => 24343, 14374 => 29995,
     30614375 => 25242, 14376 => 36741, 14377 => 20463, 14378 => 37340, 14379 => 26023,
     30714380 => 33071, 14381 => 33105, 14382 => 24220, 14383 => 33104, 14384 => 36212,
     30814385 => 21103, 14386 => 35206, 14387 => 36171, 14388 => 22797, 14389 => 20613,
     30914390 => 20184, 14391 => 38428, 14392 => 29238, 14393 => 33145, 14394 => 36127,
     31014395 => 23500, 14396 => 35747, 14397 => 38468, 14398 => 22919, 14399 => 32538,
     31114400 => 21648, 14401 => 22134, 14402 => 22030, 14403 => 35813, 14404 => 25913,
     31214405 => 27010, 14406 => 38041, 14407 => 30422, 14408 => 28297, 14409 => 24178,
     31314410 => 29976, 14411 => 26438, 14412 => 26577, 14413 => 31487, 14414 => 32925,
     31414415 => 36214, 14416 => 24863, 14417 => 31174, 14418 => 25954, 14419 => 36195,
     31514420 => 20872, 14421 => 21018, 14422 => 38050, 14423 => 32568, 14424 => 32923,
     31614425 => 32434, 14426 => 23703, 14427 => 28207, 14428 => 26464, 14429 => 31705,
     31714430 => 30347, 14431 => 39640, 14432 => 33167, 14433 => 32660, 14434 => 31957,
     31814435 => 25630, 14436 => 38224, 14437 => 31295, 14438 => 21578, 14439 => 21733,
     31914440 => 27468, 14441 => 25601, 14442 => 25096, 14443 => 40509, 14444 => 33011,
     32014445 => 30105, 14446 => 21106, 14447 => 38761, 14448 => 33883, 14449 => 26684,
     32114450 => 34532, 14451 => 38401, 14452 => 38548, 14453 => 38124, 14454 => 20010,
     32214455 => 21508, 14456 => 32473, 14457 => 26681, 14458 => 36319, 14459 => 32789,
     32314460 => 26356, 14461 => 24218, 14462 => 32697, 14625 => 22466, 14626 => 32831,
     32414627 => 26775, 14628 => 24037, 14629 => 25915, 14630 => 21151, 14631 => 24685,
     32514632 => 40858, 14633 => 20379, 14634 => 36524, 14635 => 20844, 14636 => 23467,
     32614637 => 24339, 14638 => 24041, 14639 => 27742, 14640 => 25329, 14641 => 36129,
     32714642 => 20849, 14643 => 38057, 14644 => 21246, 14645 => 27807, 14646 => 33503,
     32814647 => 29399, 14648 => 22434, 14649 => 26500, 14650 => 36141, 14651 => 22815,
     32914652 => 36764, 14653 => 33735, 14654 => 21653, 14655 => 31629, 14656 => 20272,
     33014657 => 27837, 14658 => 23396, 14659 => 22993, 14660 => 40723, 14661 => 21476,
     33114662 => 34506, 14663 => 39592, 14664 => 35895, 14665 => 32929, 14666 => 25925,
     33214667 => 39038, 14668 => 22266, 14669 => 38599, 14670 => 21038, 14671 => 29916,
     33314672 => 21072, 14673 => 23521, 14674 => 25346, 14675 => 35074, 14676 => 20054,
     33414677 => 25296, 14678 => 24618, 14679 => 26874, 14680 => 20851, 14681 => 23448,
     33514682 => 20896, 14683 => 35266, 14684 => 31649, 14685 => 39302, 14686 => 32592,
     33614687 => 24815, 14688 => 28748, 14689 => 36143, 14690 => 20809, 14691 => 24191,
     33714692 => 36891, 14693 => 29808, 14694 => 35268, 14695 => 22317, 14696 => 30789,
     33814697 => 24402, 14698 => 40863, 14699 => 38394, 14700 => 36712, 14701 => 39740,
     33914702 => 35809, 14703 => 30328, 14704 => 26690, 14705 => 26588, 14706 => 36330,
     34014707 => 36149, 14708 => 21053, 14709 => 36746, 14710 => 28378, 14711 => 26829,
     34114712 => 38149, 14713 => 37101, 14714 => 22269, 14715 => 26524, 14716 => 35065,
     34214717 => 36807, 14718 => 21704, 14881 => 39608, 14882 => 23401, 14883 => 28023,
     34314884 => 27686, 14885 => 20133, 14886 => 23475, 14887 => 39559, 14888 => 37219,
     34414889 => 25000, 14890 => 37039, 14891 => 38889, 14892 => 21547, 14893 => 28085,
     34514894 => 23506, 14895 => 20989, 14896 => 21898, 14897 => 32597, 14898 => 32752,
     34614899 => 25788, 14900 => 25421, 14901 => 26097, 14902 => 25022, 14903 => 24717,
     34714904 => 28938, 14905 => 27735, 14906 => 27721, 14907 => 22831, 14908 => 26477,
     34814909 => 33322, 14910 => 22741, 14911 => 22158, 14912 => 35946, 14913 => 27627,
     34914914 => 37085, 14915 => 22909, 14916 => 32791, 14917 => 21495, 14918 => 28009,
     35014919 => 21621, 14920 => 21917, 14921 => 33655, 14922 => 33743, 14923 => 26680,
     35114924 => 31166, 14925 => 21644, 14926 => 20309, 14927 => 21512, 14928 => 30418,
     35214929 => 35977, 14930 => 38402, 14931 => 27827, 14932 => 28088, 14933 => 36203,
     35314934 => 35088, 14935 => 40548, 14936 => 36154, 14937 => 22079, 14938 => 40657,
     35414939 => 30165, 14940 => 24456, 14941 => 29408, 14942 => 24680, 14943 => 21756,
     35514944 => 20136, 14945 => 27178, 14946 => 34913, 14947 => 24658, 14948 => 36720,
     35614949 => 21700, 14950 => 28888, 14951 => 34425, 14952 => 40511, 14953 => 27946,
     35714954 => 23439, 14955 => 24344, 14956 => 32418, 14957 => 21897, 14958 => 20399,
     35814959 => 29492, 14960 => 21564, 14961 => 21402, 14962 => 20505, 14963 => 21518,
     35914964 => 21628, 14965 => 20046, 14966 => 24573, 14967 => 29786, 14968 => 22774,
     36014969 => 33899, 14970 => 32993, 14971 => 34676, 14972 => 29392, 14973 => 31946,
     36114974 => 28246, 15137 => 24359, 15138 => 34382, 15139 => 21804, 15140 => 25252,
     36215141 => 20114, 15142 => 27818, 15143 => 25143, 15144 => 33457, 15145 => 21719,
     36315146 => 21326, 15147 => 29502, 15148 => 28369, 15149 => 30011, 15150 => 21010,
     36415151 => 21270, 15152 => 35805, 15153 => 27088, 15154 => 24458, 15155 => 24576,
     36515156 => 28142, 15157 => 22351, 15158 => 27426, 15159 => 29615, 15160 => 26707,
     36615161 => 36824, 15162 => 32531, 15163 => 25442, 15164 => 24739, 15165 => 21796,
     36715166 => 30186, 15167 => 35938, 15168 => 28949, 15169 => 28067, 15170 => 23462,
     36815171 => 24187, 15172 => 33618, 15173 => 24908, 15174 => 40644, 15175 => 30970,
     36915176 => 34647, 15177 => 31783, 15178 => 30343, 15179 => 20976, 15180 => 24822,
     37015181 => 29004, 15182 => 26179, 15183 => 24140, 15184 => 24653, 15185 => 35854,
     37115186 => 28784, 15187 => 25381, 15188 => 36745, 15189 => 24509, 15190 => 24674,
     37215191 => 34516, 15192 => 22238, 15193 => 27585, 15194 => 24724, 15195 => 24935,
     37315196 => 21321, 15197 => 24800, 15198 => 26214, 15199 => 36159, 15200 => 31229,
     37415201 => 20250, 15202 => 28905, 15203 => 27719, 15204 => 35763, 15205 => 35826,
     37515206 => 32472, 15207 => 33636, 15208 => 26127, 15209 => 23130, 15210 => 39746,
     37615211 => 27985, 15212 => 28151, 15213 => 35905, 15214 => 27963, 15215 => 20249,
     37715216 => 28779, 15217 => 33719, 15218 => 25110, 15219 => 24785, 15220 => 38669,
     37815221 => 36135, 15222 => 31096, 15223 => 20987, 15224 => 22334, 15225 => 22522,
     37915226 => 26426, 15227 => 30072, 15228 => 31293, 15229 => 31215, 15230 => 31637,
     38015393 => 32908, 15394 => 39269, 15395 => 36857, 15396 => 28608, 15397 => 35749,
     38115398 => 40481, 15399 => 23020, 15400 => 32489, 15401 => 32521, 15402 => 21513,
     38215403 => 26497, 15404 => 26840, 15405 => 36753, 15406 => 31821, 15407 => 38598,
     38315408 => 21450, 15409 => 24613, 15410 => 30142, 15411 => 27762, 15412 => 21363,
     38415413 => 23241, 15414 => 32423, 15415 => 25380, 15416 => 20960, 15417 => 33034,
     38515418 => 24049, 15419 => 34015, 15420 => 25216, 15421 => 20864, 15422 => 23395,
     38615423 => 20238, 15424 => 31085, 15425 => 21058, 15426 => 24760, 15427 => 27982,
     38715428 => 23492, 15429 => 23490, 15430 => 35745, 15431 => 35760, 15432 => 26082,
     38815433 => 24524, 15434 => 38469, 15435 => 22931, 15436 => 32487, 15437 => 32426,
     38915438 => 22025, 15439 => 26551, 15440 => 22841, 15441 => 20339, 15442 => 23478,
     39015443 => 21152, 15444 => 33626, 15445 => 39050, 15446 => 36158, 15447 => 30002,
     39115448 => 38078, 15449 => 20551, 15450 => 31292, 15451 => 20215, 15452 => 26550,
     39215453 => 39550, 15454 => 23233, 15455 => 27516, 15456 => 30417, 15457 => 22362,
     39315458 => 23574, 15459 => 31546, 15460 => 38388, 15461 => 29006, 15462 => 20860,
     39415463 => 32937, 15464 => 33392, 15465 => 22904, 15466 => 32516, 15467 => 33575,
     39515468 => 26816, 15469 => 26604, 15470 => 30897, 15471 => 30839, 15472 => 25315,
     39615473 => 25441, 15474 => 31616, 15475 => 20461, 15476 => 21098, 15477 => 20943,
     39715478 => 33616, 15479 => 27099, 15480 => 37492, 15481 => 36341, 15482 => 36145,
     39815483 => 35265, 15484 => 38190, 15485 => 31661, 15486 => 20214, 15649 => 20581,
     39915650 => 33328, 15651 => 21073, 15652 => 39279, 15653 => 28176, 15654 => 28293,
     40015655 => 28071, 15656 => 24314, 15657 => 20725, 15658 => 23004, 15659 => 23558,
     40115660 => 27974, 15661 => 27743, 15662 => 30086, 15663 => 33931, 15664 => 26728,
     40215665 => 22870, 15666 => 35762, 15667 => 21280, 15668 => 37233, 15669 => 38477,
     40315670 => 34121, 15671 => 26898, 15672 => 30977, 15673 => 28966, 15674 => 33014,
     40415675 => 20132, 15676 => 37066, 15677 => 27975, 15678 => 39556, 15679 => 23047,
     40515680 => 22204, 15681 => 25605, 15682 => 38128, 15683 => 30699, 15684 => 20389,
     40615685 => 33050, 15686 => 29409, 15687 => 35282, 15688 => 39290, 15689 => 32564,
     40715690 => 32478, 15691 => 21119, 15692 => 25945, 15693 => 37237, 15694 => 36735,
     40815695 => 36739, 15696 => 21483, 15697 => 31382, 15698 => 25581, 15699 => 25509,
     40915700 => 30342, 15701 => 31224, 15702 => 34903, 15703 => 38454, 15704 => 25130,
     41015705 => 21163, 15706 => 33410, 15707 => 26708, 15708 => 26480, 15709 => 25463,
     41115710 => 30571, 15711 => 31469, 15712 => 27905, 15713 => 32467, 15714 => 35299,
     41215715 => 22992, 15716 => 25106, 15717 => 34249, 15718 => 33445, 15719 => 30028,
     41315720 => 20511, 15721 => 20171, 15722 => 30117, 15723 => 35819, 15724 => 23626,
     41415725 => 24062, 15726 => 31563, 15727 => 26020, 15728 => 37329, 15729 => 20170,
     41515730 => 27941, 15731 => 35167, 15732 => 32039, 15733 => 38182, 15734 => 20165,
     41615735 => 35880, 15736 => 36827, 15737 => 38771, 15738 => 26187, 15739 => 31105,
     41715740 => 36817, 15741 => 28908, 15742 => 28024, 15905 => 23613, 15906 => 21170,
     41815907 => 33606, 15908 => 20834, 15909 => 33550, 15910 => 30555, 15911 => 26230,
     41915912 => 40120, 15913 => 20140, 15914 => 24778, 15915 => 31934, 15916 => 31923,
     42015917 => 32463, 15918 => 20117, 15919 => 35686, 15920 => 26223, 15921 => 39048,
     42115922 => 38745, 15923 => 22659, 15924 => 25964, 15925 => 38236, 15926 => 24452,
     42215927 => 30153, 15928 => 38742, 15929 => 31455, 15930 => 31454, 15931 => 20928,
     42315932 => 28847, 15933 => 31384, 15934 => 25578, 15935 => 31350, 15936 => 32416,
     42415937 => 29590, 15938 => 38893, 15939 => 20037, 15940 => 28792, 15941 => 20061,
     42515942 => 37202, 15943 => 21417, 15944 => 25937, 15945 => 26087, 15946 => 33276,
     42615947 => 33285, 15948 => 21646, 15949 => 23601, 15950 => 30106, 15951 => 38816,
     42715952 => 25304, 15953 => 29401, 15954 => 30141, 15955 => 23621, 15956 => 39545,
     42815957 => 33738, 15958 => 23616, 15959 => 21632, 15960 => 30697, 15961 => 20030,
     42915962 => 27822, 15963 => 32858, 15964 => 25298, 15965 => 25454, 15966 => 24040,
     43015967 => 20855, 15968 => 36317, 15969 => 36382, 15970 => 38191, 15971 => 20465,
     43115972 => 21477, 15973 => 24807, 15974 => 28844, 15975 => 21095, 15976 => 25424,
     43215977 => 40515, 15978 => 23071, 15979 => 20518, 15980 => 30519, 15981 => 21367,
     43315982 => 32482, 15983 => 25733, 15984 => 25899, 15985 => 25225, 15986 => 25496,
     43415987 => 20500, 15988 => 29237, 15989 => 35273, 15990 => 20915, 15991 => 35776,
     43515992 => 32477, 15993 => 22343, 15994 => 33740, 15995 => 38055, 15996 => 20891,
     43615997 => 21531, 15998 => 23803, 16161 => 20426, 16162 => 31459, 16163 => 27994,
     43716164 => 37089, 16165 => 39567, 16166 => 21888, 16167 => 21654, 16168 => 21345,
     43816169 => 21679, 16170 => 24320, 16171 => 25577, 16172 => 26999, 16173 => 20975,
     43916174 => 24936, 16175 => 21002, 16176 => 22570, 16177 => 21208, 16178 => 22350,
     44016179 => 30733, 16180 => 30475, 16181 => 24247, 16182 => 24951, 16183 => 31968,
     44116184 => 25179, 16185 => 25239, 16186 => 20130, 16187 => 28821, 16188 => 32771,
     44216189 => 25335, 16190 => 28900, 16191 => 38752, 16192 => 22391, 16193 => 33499,
     44316194 => 26607, 16195 => 26869, 16196 => 30933, 16197 => 39063, 16198 => 31185,
     44416199 => 22771, 16200 => 21683, 16201 => 21487, 16202 => 28212, 16203 => 20811,
     44516204 => 21051, 16205 => 23458, 16206 => 35838, 16207 => 32943, 16208 => 21827,
     44616209 => 22438, 16210 => 24691, 16211 => 22353, 16212 => 21549, 16213 => 31354,
     44716214 => 24656, 16215 => 23380, 16216 => 25511, 16217 => 25248, 16218 => 21475,
     44816219 => 25187, 16220 => 23495, 16221 => 26543, 16222 => 21741, 16223 => 31391,
     44916224 => 33510, 16225 => 37239, 16226 => 24211, 16227 => 35044, 16228 => 22840,
     45016229 => 22446, 16230 => 25358, 16231 => 36328, 16232 => 33007, 16233 => 22359,
     45116234 => 31607, 16235 => 20393, 16236 => 24555, 16237 => 23485, 16238 => 27454,
     45216239 => 21281, 16240 => 31568, 16241 => 29378, 16242 => 26694, 16243 => 30719,
     45316244 => 30518, 16245 => 26103, 16246 => 20917, 16247 => 20111, 16248 => 30420,
     45416249 => 23743, 16250 => 31397, 16251 => 33909, 16252 => 22862, 16253 => 39745,
     45516254 => 20608, 16417 => 39304, 16418 => 24871, 16419 => 28291, 16420 => 22372,
     45616421 => 26118, 16422 => 25414, 16423 => 22256, 16424 => 25324, 16425 => 25193,
     45716426 => 24275, 16427 => 38420, 16428 => 22403, 16429 => 25289, 16430 => 21895,
     45816431 => 34593, 16432 => 33098, 16433 => 36771, 16434 => 21862, 16435 => 33713,
     45916436 => 26469, 16437 => 36182, 16438 => 34013, 16439 => 23146, 16440 => 26639,
     46016441 => 25318, 16442 => 31726, 16443 => 38417, 16444 => 20848, 16445 => 28572,
     46116446 => 35888, 16447 => 25597, 16448 => 35272, 16449 => 25042, 16450 => 32518,
     46216451 => 28866, 16452 => 28389, 16453 => 29701, 16454 => 27028, 16455 => 29436,
     46316456 => 24266, 16457 => 37070, 16458 => 26391, 16459 => 28010, 16460 => 25438,
     46416461 => 21171, 16462 => 29282, 16463 => 32769, 16464 => 20332, 16465 => 23013,
     46516466 => 37226, 16467 => 28889, 16468 => 28061, 16469 => 21202, 16470 => 20048,
     46616471 => 38647, 16472 => 38253, 16473 => 34174, 16474 => 30922, 16475 => 32047,
     46716476 => 20769, 16477 => 22418, 16478 => 25794, 16479 => 32907, 16480 => 31867,
     46816481 => 27882, 16482 => 26865, 16483 => 26974, 16484 => 20919, 16485 => 21400,
     46916486 => 26792, 16487 => 29313, 16488 => 40654, 16489 => 31729, 16490 => 29432,
     47016491 => 31163, 16492 => 28435, 16493 => 29702, 16494 => 26446, 16495 => 37324,
     47116496 => 40100, 16497 => 31036, 16498 => 33673, 16499 => 33620, 16500 => 21519,
     47216501 => 26647, 16502 => 20029, 16503 => 21385, 16504 => 21169, 16505 => 30782,
     47316506 => 21382, 16507 => 21033, 16508 => 20616, 16509 => 20363, 16510 => 20432,
     47416673 => 30178, 16674 => 31435, 16675 => 31890, 16676 => 27813, 16677 => 38582,
     47516678 => 21147, 16679 => 29827, 16680 => 21737, 16681 => 20457, 16682 => 32852,
     47616683 => 33714, 16684 => 36830, 16685 => 38256, 16686 => 24265, 16687 => 24604,
     47716688 => 28063, 16689 => 24088, 16690 => 25947, 16691 => 33080, 16692 => 38142,
     47816693 => 24651, 16694 => 28860, 16695 => 32451, 16696 => 31918, 16697 => 20937,
     47916698 => 26753, 16699 => 31921, 16700 => 33391, 16701 => 20004, 16702 => 36742,
     48016703 => 37327, 16704 => 26238, 16705 => 20142, 16706 => 35845, 16707 => 25769,
     48116708 => 32842, 16709 => 20698, 16710 => 30103, 16711 => 29134, 16712 => 23525,
     48216713 => 36797, 16714 => 28518, 16715 => 20102, 16716 => 25730, 16717 => 38243,
     48316718 => 24278, 16719 => 26009, 16720 => 21015, 16721 => 35010, 16722 => 28872,
     48416723 => 21155, 16724 => 29454, 16725 => 29747, 16726 => 26519, 16727 => 30967,
     48516728 => 38678, 16729 => 20020, 16730 => 37051, 16731 => 40158, 16732 => 28107,
     48616733 => 20955, 16734 => 36161, 16735 => 21533, 16736 => 25294, 16737 => 29618,
     48716738 => 33777, 16739 => 38646, 16740 => 40836, 16741 => 38083, 16742 => 20278,
     48816743 => 32666, 16744 => 20940, 16745 => 28789, 16746 => 38517, 16747 => 23725,
     48916748 => 39046, 16749 => 21478, 16750 => 20196, 16751 => 28316, 16752 => 29705,
     49016753 => 27060, 16754 => 30827, 16755 => 39311, 16756 => 30041, 16757 => 21016,
     49116758 => 30244, 16759 => 27969, 16760 => 26611, 16761 => 20845, 16762 => 40857,
     49216763 => 32843, 16764 => 21657, 16765 => 31548, 16766 => 31423, 16929 => 38534,
     49316930 => 22404, 16931 => 25314, 16932 => 38471, 16933 => 27004, 16934 => 23044,
     49416935 => 25602, 16936 => 31699, 16937 => 28431, 16938 => 38475, 16939 => 33446,
     49516940 => 21346, 16941 => 39045, 16942 => 24208, 16943 => 28809, 16944 => 25523,
     49616945 => 21348, 16946 => 34383, 16947 => 40065, 16948 => 40595, 16949 => 30860,
     49716950 => 38706, 16951 => 36335, 16952 => 36162, 16953 => 40575, 16954 => 28510,
     49816955 => 31108, 16956 => 24405, 16957 => 38470, 16958 => 25134, 16959 => 39540,
     49916960 => 21525, 16961 => 38109, 16962 => 20387, 16963 => 26053, 16964 => 23653,
     50016965 => 23649, 16966 => 32533, 16967 => 34385, 16968 => 27695, 16969 => 24459,
     50116970 => 29575, 16971 => 28388, 16972 => 32511, 16973 => 23782, 16974 => 25371,
     50216975 => 23402, 16976 => 28390, 16977 => 21365, 16978 => 20081, 16979 => 25504,
     50316980 => 30053, 16981 => 25249, 16982 => 36718, 16983 => 20262, 16984 => 20177,
     50416985 => 27814, 16986 => 32438, 16987 => 35770, 16988 => 33821, 16989 => 34746,
     50516990 => 32599, 16991 => 36923, 16992 => 38179, 16993 => 31657, 16994 => 39585,
     50616995 => 35064, 16996 => 33853, 16997 => 27931, 16998 => 39558, 16999 => 32476,
     50717000 => 22920, 17001 => 40635, 17002 => 29595, 17003 => 30721, 17004 => 34434,
     50817005 => 39532, 17006 => 39554, 17007 => 22043, 17008 => 21527, 17009 => 22475,
     50917010 => 20080, 17011 => 40614, 17012 => 21334, 17013 => 36808, 17014 => 33033,
     51017015 => 30610, 17016 => 39314, 17017 => 34542, 17018 => 28385, 17019 => 34067,
     51117020 => 26364, 17021 => 24930, 17022 => 28459, 17185 => 35881, 17186 => 33426,
     51217187 => 33579, 17188 => 30450, 17189 => 27667, 17190 => 24537, 17191 => 33725,
     51317192 => 29483, 17193 => 33541, 17194 => 38170, 17195 => 27611, 17196 => 30683,
     51417197 => 38086, 17198 => 21359, 17199 => 33538, 17200 => 20882, 17201 => 24125,
     51517202 => 35980, 17203 => 36152, 17204 => 20040, 17205 => 29611, 17206 => 26522,
     51617207 => 26757, 17208 => 37238, 17209 => 38665, 17210 => 29028, 17211 => 27809,
     51717212 => 30473, 17213 => 23186, 17214 => 38209, 17215 => 27599, 17216 => 32654,
     51817217 => 26151, 17218 => 23504, 17219 => 22969, 17220 => 23194, 17221 => 38376,
     51917222 => 38391, 17223 => 20204, 17224 => 33804, 17225 => 33945, 17226 => 27308,
     52017227 => 30431, 17228 => 38192, 17229 => 29467, 17230 => 26790, 17231 => 23391,
     52117232 => 30511, 17233 => 37274, 17234 => 38753, 17235 => 31964, 17236 => 36855,
     52217237 => 35868, 17238 => 24357, 17239 => 31859, 17240 => 31192, 17241 => 35269,
     52317242 => 27852, 17243 => 34588, 17244 => 23494, 17245 => 24130, 17246 => 26825,
     52417247 => 30496, 17248 => 32501, 17249 => 20885, 17250 => 20813, 17251 => 21193,
     52517252 => 23081, 17253 => 32517, 17254 => 38754, 17255 => 33495, 17256 => 25551,
     52617257 => 30596, 17258 => 34256, 17259 => 31186, 17260 => 28218, 17261 => 24217,
     52717262 => 22937, 17263 => 34065, 17264 => 28781, 17265 => 27665, 17266 => 25279,
     52817267 => 30399, 17268 => 25935, 17269 => 24751, 17270 => 38397, 17271 => 26126,
     52917272 => 34719, 17273 => 40483, 17274 => 38125, 17275 => 21517, 17276 => 21629,
     53017277 => 35884, 17278 => 25720, 17441 => 25721, 17442 => 34321, 17443 => 27169,
     53117444 => 33180, 17445 => 30952, 17446 => 25705, 17447 => 39764, 17448 => 25273,
     53217449 => 26411, 17450 => 33707, 17451 => 22696, 17452 => 40664, 17453 => 27819,
     53317454 => 28448, 17455 => 23518, 17456 => 38476, 17457 => 35851, 17458 => 29279,
     53417459 => 26576, 17460 => 25287, 17461 => 29281, 17462 => 20137, 17463 => 22982,
     53517464 => 27597, 17465 => 22675, 17466 => 26286, 17467 => 24149, 17468 => 21215,
     53617469 => 24917, 17470 => 26408, 17471 => 30446, 17472 => 30566, 17473 => 29287,
     53717474 => 31302, 17475 => 25343, 17476 => 21738, 17477 => 21584, 17478 => 38048,
     53817479 => 37027, 17480 => 23068, 17481 => 32435, 17482 => 27670, 17483 => 20035,
     53917484 => 22902, 17485 => 32784, 17486 => 22856, 17487 => 21335, 17488 => 30007,
     54017489 => 38590, 17490 => 22218, 17491 => 25376, 17492 => 33041, 17493 => 24700,
     54117494 => 38393, 17495 => 28118, 17496 => 21602, 17497 => 39297, 17498 => 20869,
     54217499 => 23273, 17500 => 33021, 17501 => 22958, 17502 => 38675, 17503 => 20522,
     54317504 => 27877, 17505 => 23612, 17506 => 25311, 17507 => 20320, 17508 => 21311,
     54417509 => 33147, 17510 => 36870, 17511 => 28346, 17512 => 34091, 17513 => 25288,
     54517514 => 24180, 17515 => 30910, 17516 => 25781, 17517 => 25467, 17518 => 24565,
     54617519 => 23064, 17520 => 37247, 17521 => 40479, 17522 => 23615, 17523 => 25423,
     54717524 => 32834, 17525 => 23421, 17526 => 21870, 17527 => 38218, 17528 => 38221,
     54817529 => 28037, 17530 => 24744, 17531 => 26592, 17532 => 29406, 17533 => 20957,
     54917534 => 23425, 17697 => 25319, 17698 => 27870, 17699 => 29275, 17700 => 25197,
     55017701 => 38062, 17702 => 32445, 17703 => 33043, 17704 => 27987, 17705 => 20892,
     55117706 => 24324, 17707 => 22900, 17708 => 21162, 17709 => 24594, 17710 => 22899,
     55217711 => 26262, 17712 => 34384, 17713 => 30111, 17714 => 25386, 17715 => 25062,
     55317716 => 31983, 17717 => 35834, 17718 => 21734, 17719 => 27431, 17720 => 40485,
     55417721 => 27572, 17722 => 34261, 17723 => 21589, 17724 => 20598, 17725 => 27812,
     55517726 => 21866, 17727 => 36276, 17728 => 29228, 17729 => 24085, 17730 => 24597,
     55617731 => 29750, 17732 => 25293, 17733 => 25490, 17734 => 29260, 17735 => 24472,
     55717736 => 28227, 17737 => 27966, 17738 => 25856, 17739 => 28504, 17740 => 30424,
     55817741 => 30928, 17742 => 30460, 17743 => 30036, 17744 => 21028, 17745 => 21467,
     55917746 => 20051, 17747 => 24222, 17748 => 26049, 17749 => 32810, 17750 => 32982,
     56017751 => 25243, 17752 => 21638, 17753 => 21032, 17754 => 28846, 17755 => 34957,
     56117756 => 36305, 17757 => 27873, 17758 => 21624, 17759 => 32986, 17760 => 22521,
     56217761 => 35060, 17762 => 36180, 17763 => 38506, 17764 => 37197, 17765 => 20329,
     56317766 => 27803, 17767 => 21943, 17768 => 30406, 17769 => 30768, 17770 => 25256,
     56417771 => 28921, 17772 => 28558, 17773 => 24429, 17774 => 34028, 17775 => 26842,
     56517776 => 30844, 17777 => 31735, 17778 => 33192, 17779 => 26379, 17780 => 40527,
     56617781 => 25447, 17782 => 30896, 17783 => 22383, 17784 => 30738, 17785 => 38713,
     56717786 => 25209, 17787 => 25259, 17788 => 21128, 17789 => 29749, 17790 => 27607,
     56817953 => 21860, 17954 => 33086, 17955 => 30130, 17956 => 30382, 17957 => 21305,
     56917958 => 30174, 17959 => 20731, 17960 => 23617, 17961 => 35692, 17962 => 31687,
     57017963 => 20559, 17964 => 29255, 17965 => 39575, 17966 => 39128, 17967 => 28418,
     57117968 => 29922, 17969 => 31080, 17970 => 25735, 17971 => 30629, 17972 => 25340,
     57217973 => 39057, 17974 => 36139, 17975 => 21697, 17976 => 32856, 17977 => 20050,
     57317978 => 22378, 17979 => 33529, 17980 => 33805, 17981 => 24179, 17982 => 20973,
     57417983 => 29942, 17984 => 35780, 17985 => 23631, 17986 => 22369, 17987 => 27900,
     57517988 => 39047, 17989 => 23110, 17990 => 30772, 17991 => 39748, 17992 => 36843,
     57617993 => 31893, 17994 => 21078, 17995 => 25169, 17996 => 38138, 17997 => 20166,
     57717998 => 33670, 17999 => 33889, 18000 => 33769, 18001 => 33970, 18002 => 22484,
     57818003 => 26420, 18004 => 22275, 18005 => 26222, 18006 => 28006, 18007 => 35889,
     57918008 => 26333, 18009 => 28689, 18010 => 26399, 18011 => 27450, 18012 => 26646,
     58018013 => 25114, 18014 => 22971, 18015 => 19971, 18016 => 20932, 18017 => 28422,
     58118018 => 26578, 18019 => 27791, 18020 => 20854, 18021 => 26827, 18022 => 22855,
     58218023 => 27495, 18024 => 30054, 18025 => 23822, 18026 => 33040, 18027 => 40784,
     58318028 => 26071, 18029 => 31048, 18030 => 31041, 18031 => 39569, 18032 => 36215,
     58418033 => 23682, 18034 => 20062, 18035 => 20225, 18036 => 21551, 18037 => 22865,
     58518038 => 30732, 18039 => 22120, 18040 => 27668, 18041 => 36804, 18042 => 24323,
     58618043 => 27773, 18044 => 27875, 18045 => 35755, 18046 => 25488, 18209 => 24688,
     58718210 => 27965, 18211 => 29301, 18212 => 25190, 18213 => 38030, 18214 => 38085,
     58818215 => 21315, 18216 => 36801, 18217 => 31614, 18218 => 20191, 18219 => 35878,
     58918220 => 20094, 18221 => 40660, 18222 => 38065, 18223 => 38067, 18224 => 21069,
     59018225 => 28508, 18226 => 36963, 18227 => 27973, 18228 => 35892, 18229 => 22545,
     59118230 => 23884, 18231 => 27424, 18232 => 27465, 18233 => 26538, 18234 => 21595,
     59218235 => 33108, 18236 => 32652, 18237 => 22681, 18238 => 34103, 18239 => 24378,
     59318240 => 25250, 18241 => 27207, 18242 => 38201, 18243 => 25970, 18244 => 24708,
     59418245 => 26725, 18246 => 30631, 18247 => 20052, 18248 => 20392, 18249 => 24039,
     59518250 => 38808, 18251 => 25772, 18252 => 32728, 18253 => 23789, 18254 => 20431,
     59618255 => 31373, 18256 => 20999, 18257 => 33540, 18258 => 19988, 18259 => 24623,
     59718260 => 31363, 18261 => 38054, 18262 => 20405, 18263 => 20146, 18264 => 31206,
     59818265 => 29748, 18266 => 21220, 18267 => 33465, 18268 => 25810, 18269 => 31165,
     59918270 => 23517, 18271 => 27777, 18272 => 38738, 18273 => 36731, 18274 => 27682,
     60018275 => 20542, 18276 => 21375, 18277 => 28165, 18278 => 25806, 18279 => 26228,
     60118280 => 27696, 18281 => 24773, 18282 => 39031, 18283 => 35831, 18284 => 24198,
     60218285 => 29756, 18286 => 31351, 18287 => 31179, 18288 => 19992, 18289 => 37041,
     60318290 => 29699, 18291 => 27714, 18292 => 22234, 18293 => 37195, 18294 => 27845,
     60418295 => 36235, 18296 => 21306, 18297 => 34502, 18298 => 26354, 18299 => 36527,
     60518300 => 23624, 18301 => 39537, 18302 => 28192, 18465 => 21462, 18466 => 23094,
     60618467 => 40843, 18468 => 36259, 18469 => 21435, 18470 => 22280, 18471 => 39079,
     60718472 => 26435, 18473 => 37275, 18474 => 27849, 18475 => 20840, 18476 => 30154,
     60818477 => 25331, 18478 => 29356, 18479 => 21048, 18480 => 21149, 18481 => 32570,
     60918482 => 28820, 18483 => 30264, 18484 => 21364, 18485 => 40522, 18486 => 27063,
     61018487 => 30830, 18488 => 38592, 18489 => 35033, 18490 => 32676, 18491 => 28982,
     61118492 => 29123, 18493 => 20873, 18494 => 26579, 18495 => 29924, 18496 => 22756,
     61218497 => 25880, 18498 => 22199, 18499 => 35753, 18500 => 39286, 18501 => 25200,
     61318502 => 32469, 18503 => 24825, 18504 => 28909, 18505 => 22764, 18506 => 20161,
     61418507 => 20154, 18508 => 24525, 18509 => 38887, 18510 => 20219, 18511 => 35748,
     61518512 => 20995, 18513 => 22922, 18514 => 32427, 18515 => 25172, 18516 => 20173,
     61618517 => 26085, 18518 => 25102, 18519 => 33592, 18520 => 33993, 18521 => 33635,
     61718522 => 34701, 18523 => 29076, 18524 => 28342, 18525 => 23481, 18526 => 32466,
     61818527 => 20887, 18528 => 25545, 18529 => 26580, 18530 => 32905, 18531 => 33593,
     61918532 => 34837, 18533 => 20754, 18534 => 23418, 18535 => 22914, 18536 => 36785,
     62018537 => 20083, 18538 => 27741, 18539 => 20837, 18540 => 35109, 18541 => 36719,
     62118542 => 38446, 18543 => 34122, 18544 => 29790, 18545 => 38160, 18546 => 38384,
     62218547 => 28070, 18548 => 33509, 18549 => 24369, 18550 => 25746, 18551 => 27922,
     62318552 => 33832, 18553 => 33134, 18554 => 40131, 18555 => 22622, 18556 => 36187,
     62418557 => 19977, 18558 => 21441, 18721 => 20254, 18722 => 25955, 18723 => 26705,
     62518724 => 21971, 18725 => 20007, 18726 => 25620, 18727 => 39578, 18728 => 25195,
     62618729 => 23234, 18730 => 29791, 18731 => 33394, 18732 => 28073, 18733 => 26862,
     62718734 => 20711, 18735 => 33678, 18736 => 30722, 18737 => 26432, 18738 => 21049,
     62818739 => 27801, 18740 => 32433, 18741 => 20667, 18742 => 21861, 18743 => 29022,
     62918744 => 31579, 18745 => 26194, 18746 => 29642, 18747 => 33515, 18748 => 26441,
     63018749 => 23665, 18750 => 21024, 18751 => 29053, 18752 => 34923, 18753 => 38378,
     63118754 => 38485, 18755 => 25797, 18756 => 36193, 18757 => 33203, 18758 => 21892,
     63218759 => 27733, 18760 => 25159, 18761 => 32558, 18762 => 22674, 18763 => 20260,
     63318764 => 21830, 18765 => 36175, 18766 => 26188, 18767 => 19978, 18768 => 23578,
     63418769 => 35059, 18770 => 26786, 18771 => 25422, 18772 => 31245, 18773 => 28903,
     63518774 => 33421, 18775 => 21242, 18776 => 38902, 18777 => 23569, 18778 => 21736,
     63618779 => 37045, 18780 => 32461, 18781 => 22882, 18782 => 36170, 18783 => 34503,
     63718784 => 33292, 18785 => 33293, 18786 => 36198, 18787 => 25668, 18788 => 23556,
     63818789 => 24913, 18790 => 28041, 18791 => 31038, 18792 => 35774, 18793 => 30775,
     63918794 => 30003, 18795 => 21627, 18796 => 20280, 18797 => 36523, 18798 => 28145,
     64018799 => 23072, 18800 => 32453, 18801 => 31070, 18802 => 27784, 18803 => 23457,
     64118804 => 23158, 18805 => 29978, 18806 => 32958, 18807 => 24910, 18808 => 28183,
     64218809 => 22768, 18810 => 29983, 18811 => 29989, 18812 => 29298, 18813 => 21319,
     64318814 => 32499, 18977 => 30465, 18978 => 30427, 18979 => 21097, 18980 => 32988,
     64418981 => 22307, 18982 => 24072, 18983 => 22833, 18984 => 29422, 18985 => 26045,
     64518986 => 28287, 18987 => 35799, 18988 => 23608, 18989 => 34417, 18990 => 21313,
     64618991 => 30707, 18992 => 25342, 18993 => 26102, 18994 => 20160, 18995 => 39135,
     64718996 => 34432, 18997 => 23454, 18998 => 35782, 18999 => 21490, 19000 => 30690,
     64819001 => 20351, 19002 => 23630, 19003 => 39542, 19004 => 22987, 19005 => 24335,
     64919006 => 31034, 19007 => 22763, 19008 => 19990, 19009 => 26623, 19010 => 20107,
     65019011 => 25325, 19012 => 35475, 19013 => 36893, 19014 => 21183, 19015 => 26159,
     65119016 => 21980, 19017 => 22124, 19018 => 36866, 19019 => 20181, 19020 => 20365,
     65219021 => 37322, 19022 => 39280, 19023 => 27663, 19024 => 24066, 19025 => 24643,
     65319026 => 23460, 19027 => 35270, 19028 => 35797, 19029 => 25910, 19030 => 25163,
     65419031 => 39318, 19032 => 23432, 19033 => 23551, 19034 => 25480, 19035 => 21806,
     65519036 => 21463, 19037 => 30246, 19038 => 20861, 19039 => 34092, 19040 => 26530,
     65619041 => 26803, 19042 => 27530, 19043 => 25234, 19044 => 36755, 19045 => 21460,
     65719046 => 33298, 19047 => 28113, 19048 => 30095, 19049 => 20070, 19050 => 36174,
     65819051 => 23408, 19052 => 29087, 19053 => 34223, 19054 => 26257, 19055 => 26329,
     65919056 => 32626, 19057 => 34560, 19058 => 40653, 19059 => 40736, 19060 => 23646,
     66019061 => 26415, 19062 => 36848, 19063 => 26641, 19064 => 26463, 19065 => 25101,
     66119066 => 31446, 19067 => 22661, 19068 => 24246, 19069 => 25968, 19070 => 28465,
     66219233 => 24661, 19234 => 21047, 19235 => 32781, 19236 => 25684, 19237 => 34928,
     66319238 => 29993, 19239 => 24069, 19240 => 26643, 19241 => 25332, 19242 => 38684,
     66419243 => 21452, 19244 => 29245, 19245 => 35841, 19246 => 27700, 19247 => 30561,
     66519248 => 31246, 19249 => 21550, 19250 => 30636, 19251 => 39034, 19252 => 33308,
     66619253 => 35828, 19254 => 30805, 19255 => 26388, 19256 => 28865, 19257 => 26031,
     66719258 => 25749, 19259 => 22070, 19260 => 24605, 19261 => 31169, 19262 => 21496,
     66819263 => 19997, 19264 => 27515, 19265 => 32902, 19266 => 23546, 19267 => 21987,
     66919268 => 22235, 19269 => 20282, 19270 => 20284, 19271 => 39282, 19272 => 24051,
     67019273 => 26494, 19274 => 32824, 19275 => 24578, 19276 => 39042, 19277 => 36865,
     67119278 => 23435, 19279 => 35772, 19280 => 35829, 19281 => 25628, 19282 => 33368,
     67219283 => 25822, 19284 => 22013, 19285 => 33487, 19286 => 37221, 19287 => 20439,
     67319288 => 32032, 19289 => 36895, 19290 => 31903, 19291 => 20723, 19292 => 22609,
     67419293 => 28335, 19294 => 23487, 19295 => 35785, 19296 => 32899, 19297 => 37240,
     67519298 => 33948, 19299 => 31639, 19300 => 34429, 19301 => 38539, 19302 => 38543,
     67619303 => 32485, 19304 => 39635, 19305 => 30862, 19306 => 23681, 19307 => 31319,
     67719308 => 36930, 19309 => 38567, 19310 => 31071, 19311 => 23385, 19312 => 25439,
     67819313 => 31499, 19314 => 34001, 19315 => 26797, 19316 => 21766, 19317 => 32553,
     67919318 => 29712, 19319 => 32034, 19320 => 38145, 19321 => 25152, 19322 => 22604,
     68019323 => 20182, 19324 => 23427, 19325 => 22905, 19326 => 22612, 19489 => 29549,
     68119490 => 25374, 19491 => 36427, 19492 => 36367, 19493 => 32974, 19494 => 33492,
     68219495 => 25260, 19496 => 21488, 19497 => 27888, 19498 => 37214, 19499 => 22826,
     68319500 => 24577, 19501 => 27760, 19502 => 22349, 19503 => 25674, 19504 => 36138,
     68419505 => 30251, 19506 => 28393, 19507 => 22363, 19508 => 27264, 19509 => 30192,
     68519510 => 28525, 19511 => 35885, 19512 => 35848, 19513 => 22374, 19514 => 27631,
     68619515 => 34962, 19516 => 30899, 19517 => 25506, 19518 => 21497, 19519 => 28845,
     68719520 => 27748, 19521 => 22616, 19522 => 25642, 19523 => 22530, 19524 => 26848,
     68819525 => 33179, 19526 => 21776, 19527 => 31958, 19528 => 20504, 19529 => 36538,
     68919530 => 28108, 19531 => 36255, 19532 => 28907, 19533 => 25487, 19534 => 28059,
     69019535 => 28372, 19536 => 32486, 19537 => 33796, 19538 => 26691, 19539 => 36867,
     69119540 => 28120, 19541 => 38518, 19542 => 35752, 19543 => 22871, 19544 => 29305,
     69219545 => 34276, 19546 => 33150, 19547 => 30140, 19548 => 35466, 19549 => 26799,
     69319550 => 21076, 19551 => 36386, 19552 => 38161, 19553 => 25552, 19554 => 39064,
     69419555 => 36420, 19556 => 21884, 19557 => 20307, 19558 => 26367, 19559 => 22159,
     69519560 => 24789, 19561 => 28053, 19562 => 21059, 19563 => 23625, 19564 => 22825,
     69619565 => 28155, 19566 => 22635, 19567 => 30000, 19568 => 29980, 19569 => 24684,
     69719570 => 33300, 19571 => 33094, 19572 => 25361, 19573 => 26465, 19574 => 36834,
     69819575 => 30522, 19576 => 36339, 19577 => 36148, 19578 => 38081, 19579 => 24086,
     69919580 => 21381, 19581 => 21548, 19582 => 28867, 19745 => 27712, 19746 => 24311,
     70019747 => 20572, 19748 => 20141, 19749 => 24237, 19750 => 25402, 19751 => 33351,
     70119752 => 36890, 19753 => 26704, 19754 => 37230, 19755 => 30643, 19756 => 21516,
     70219757 => 38108, 19758 => 24420, 19759 => 31461, 19760 => 26742, 19761 => 25413,
     70319762 => 31570, 19763 => 32479, 19764 => 30171, 19765 => 20599, 19766 => 25237,
     70419767 => 22836, 19768 => 36879, 19769 => 20984, 19770 => 31171, 19771 => 31361,
     70519772 => 22270, 19773 => 24466, 19774 => 36884, 19775 => 28034, 19776 => 23648,
     70619777 => 22303, 19778 => 21520, 19779 => 20820, 19780 => 28237, 19781 => 22242,
     70719782 => 25512, 19783 => 39059, 19784 => 33151, 19785 => 34581, 19786 => 35114,
     70819787 => 36864, 19788 => 21534, 19789 => 23663, 19790 => 33216, 19791 => 25302,
     70919792 => 25176, 19793 => 33073, 19794 => 40501, 19795 => 38464, 19796 => 39534,
     71019797 => 39548, 19798 => 26925, 19799 => 22949, 19800 => 25299, 19801 => 21822,
     71119802 => 25366, 19803 => 21703, 19804 => 34521, 19805 => 27964, 19806 => 23043,
     71219807 => 29926, 19808 => 34972, 19809 => 27498, 19810 => 22806, 19811 => 35916,
     71319812 => 24367, 19813 => 28286, 19814 => 29609, 19815 => 39037, 19816 => 20024,
     71419817 => 28919, 19818 => 23436, 19819 => 30871, 19820 => 25405, 19821 => 26202,
     71519822 => 30358, 19823 => 24779, 19824 => 23451, 19825 => 23113, 19826 => 19975,
     71619827 => 33109, 19828 => 27754, 19829 => 29579, 19830 => 20129, 19831 => 26505,
     71719832 => 32593, 19833 => 24448, 19834 => 26106, 19835 => 26395, 19836 => 24536,
     71819837 => 22916, 19838 => 23041, 20001 => 24013, 20002 => 24494, 20003 => 21361,
     71920004 => 38886, 20005 => 36829, 20006 => 26693, 20007 => 22260, 20008 => 21807,
     72020009 => 24799, 20010 => 20026, 20011 => 28493, 20012 => 32500, 20013 => 33479,
     72120014 => 33806, 20015 => 22996, 20016 => 20255, 20017 => 20266, 20018 => 23614,
     72220019 => 32428, 20020 => 26410, 20021 => 34074, 20022 => 21619, 20023 => 30031,
     72320024 => 32963, 20025 => 21890, 20026 => 39759, 20027 => 20301, 20028 => 28205,
     72420029 => 35859, 20030 => 23561, 20031 => 24944, 20032 => 21355, 20033 => 30239,
     72520034 => 28201, 20035 => 34442, 20036 => 25991, 20037 => 38395, 20038 => 32441,
     72620039 => 21563, 20040 => 31283, 20041 => 32010, 20042 => 38382, 20043 => 21985,
     72720044 => 32705, 20045 => 29934, 20046 => 25373, 20047 => 34583, 20048 => 28065,
     72820049 => 31389, 20050 => 25105, 20051 => 26017, 20052 => 21351, 20053 => 25569,
     72920054 => 27779, 20055 => 24043, 20056 => 21596, 20057 => 38056, 20058 => 20044,
     73020059 => 27745, 20060 => 35820, 20061 => 23627, 20062 => 26080, 20063 => 33436,
     73120064 => 26791, 20065 => 21566, 20066 => 21556, 20067 => 27595, 20068 => 27494,
     73220069 => 20116, 20070 => 25410, 20071 => 21320, 20072 => 33310, 20073 => 20237,
     73320074 => 20398, 20075 => 22366, 20076 => 25098, 20077 => 38654, 20078 => 26212,
     73420079 => 29289, 20080 => 21247, 20081 => 21153, 20082 => 24735, 20083 => 35823,
     73520084 => 26132, 20085 => 29081, 20086 => 26512, 20087 => 35199, 20088 => 30802,
     73620089 => 30717, 20090 => 26224, 20091 => 22075, 20092 => 21560, 20093 => 38177,
     73720094 => 29306, 20257 => 31232, 20258 => 24687, 20259 => 24076, 20260 => 24713,
     73820261 => 33181, 20262 => 22805, 20263 => 24796, 20264 => 29060, 20265 => 28911,
     73920266 => 28330, 20267 => 27728, 20268 => 29312, 20269 => 27268, 20270 => 34989,
     74020271 => 24109, 20272 => 20064, 20273 => 23219, 20274 => 21916, 20275 => 38115,
     74120276 => 27927, 20277 => 31995, 20278 => 38553, 20279 => 25103, 20280 => 32454,
     74220281 => 30606, 20282 => 34430, 20283 => 21283, 20284 => 38686, 20285 => 36758,
     74320286 => 26247, 20287 => 23777, 20288 => 20384, 20289 => 29421, 20290 => 19979,
     74420291 => 21414, 20292 => 22799, 20293 => 21523, 20294 => 25472, 20295 => 38184,
     74520296 => 20808, 20297 => 20185, 20298 => 40092, 20299 => 32420, 20300 => 21688,
     74620301 => 36132, 20302 => 34900, 20303 => 33335, 20304 => 38386, 20305 => 28046,
     74720306 => 24358, 20307 => 23244, 20308 => 26174, 20309 => 38505, 20310 => 29616,
     74820311 => 29486, 20312 => 21439, 20313 => 33146, 20314 => 39301, 20315 => 32673,
     74920316 => 23466, 20317 => 38519, 20318 => 38480, 20319 => 32447, 20320 => 30456,
     75020321 => 21410, 20322 => 38262, 20323 => 39321, 20324 => 31665, 20325 => 35140,
     75120326 => 28248, 20327 => 20065, 20328 => 32724, 20329 => 31077, 20330 => 35814,
     75220331 => 24819, 20332 => 21709, 20333 => 20139, 20334 => 39033, 20335 => 24055,
     75320336 => 27233, 20337 => 20687, 20338 => 21521, 20339 => 35937, 20340 => 33831,
     75420341 => 30813, 20342 => 38660, 20343 => 21066, 20344 => 21742, 20345 => 22179,
     75520346 => 38144, 20347 => 28040, 20348 => 23477, 20349 => 28102, 20350 => 26195,
     75620513 => 23567, 20514 => 23389, 20515 => 26657, 20516 => 32918, 20517 => 21880,
     75720518 => 31505, 20519 => 25928, 20520 => 26964, 20521 => 20123, 20522 => 27463,
     75820523 => 34638, 20524 => 38795, 20525 => 21327, 20526 => 25375, 20527 => 25658,
     75920528 => 37034, 20529 => 26012, 20530 => 32961, 20531 => 35856, 20532 => 20889,
     76020533 => 26800, 20534 => 21368, 20535 => 34809, 20536 => 25032, 20537 => 27844,
     76120538 => 27899, 20539 => 35874, 20540 => 23633, 20541 => 34218, 20542 => 33455,
     76220543 => 38156, 20544 => 27427, 20545 => 36763, 20546 => 26032, 20547 => 24571,
     76320548 => 24515, 20549 => 20449, 20550 => 34885, 20551 => 26143, 20552 => 33125,
     76420553 => 29481, 20554 => 24826, 20555 => 20852, 20556 => 21009, 20557 => 22411,
     76520558 => 24418, 20559 => 37026, 20560 => 34892, 20561 => 37266, 20562 => 24184,
     76620563 => 26447, 20564 => 24615, 20565 => 22995, 20566 => 20804, 20567 => 20982,
     76720568 => 33016, 20569 => 21256, 20570 => 27769, 20571 => 38596, 20572 => 29066,
     76820573 => 20241, 20574 => 20462, 20575 => 32670, 20576 => 26429, 20577 => 21957,
     76920578 => 38152, 20579 => 31168, 20580 => 34966, 20581 => 32483, 20582 => 22687,
     77020583 => 25100, 20584 => 38656, 20585 => 34394, 20586 => 22040, 20587 => 39035,
     77120588 => 24464, 20589 => 35768, 20590 => 33988, 20591 => 37207, 20592 => 21465,
     77220593 => 26093, 20594 => 24207, 20595 => 30044, 20596 => 24676, 20597 => 32110,
     77320598 => 23167, 20599 => 32490, 20600 => 32493, 20601 => 36713, 20602 => 21927,
     77420603 => 23459, 20604 => 24748, 20605 => 26059, 20606 => 29572, 20769 => 36873,
     77520770 => 30307, 20771 => 30505, 20772 => 32474, 20773 => 38772, 20774 => 34203,
     77620775 => 23398, 20776 => 31348, 20777 => 38634, 20778 => 34880, 20779 => 21195,
     77720780 => 29071, 20781 => 24490, 20782 => 26092, 20783 => 35810, 20784 => 23547,
     77820785 => 39535, 20786 => 24033, 20787 => 27529, 20788 => 27739, 20789 => 35757,
     77920790 => 35759, 20791 => 36874, 20792 => 36805, 20793 => 21387, 20794 => 25276,
     78020795 => 40486, 20796 => 40493, 20797 => 21568, 20798 => 20011, 20799 => 33469,
     78120800 => 29273, 20801 => 34460, 20802 => 23830, 20803 => 34905, 20804 => 28079,
     78220805 => 38597, 20806 => 21713, 20807 => 20122, 20808 => 35766, 20809 => 28937,
     78320810 => 21693, 20811 => 38409, 20812 => 28895, 20813 => 28153, 20814 => 30416,
     78420815 => 20005, 20816 => 30740, 20817 => 34578, 20818 => 23721, 20819 => 24310,
     78520820 => 35328, 20821 => 39068, 20822 => 38414, 20823 => 28814, 20824 => 27839,
     78620825 => 22852, 20826 => 25513, 20827 => 30524, 20828 => 34893, 20829 => 28436,
     78720830 => 33395, 20831 => 22576, 20832 => 29141, 20833 => 21388, 20834 => 30746,
     78820835 => 38593, 20836 => 21761, 20837 => 24422, 20838 => 28976, 20839 => 23476,
     78920840 => 35866, 20841 => 39564, 20842 => 27523, 20843 => 22830, 20844 => 40495,
     79020845 => 31207, 20846 => 26472, 20847 => 25196, 20848 => 20335, 20849 => 30113,
     79120850 => 32650, 20851 => 27915, 20852 => 38451, 20853 => 27687, 20854 => 20208,
     79220855 => 30162, 20856 => 20859, 20857 => 26679, 20858 => 28478, 20859 => 36992,
     79320860 => 33136, 20861 => 22934, 20862 => 29814, 21025 => 25671, 21026 => 23591,
     79421027 => 36965, 21028 => 31377, 21029 => 35875, 21030 => 23002, 21031 => 21676,
     79521032 => 33280, 21033 => 33647, 21034 => 35201, 21035 => 32768, 21036 => 26928,
     79621037 => 22094, 21038 => 32822, 21039 => 29239, 21040 => 37326, 21041 => 20918,
     79721042 => 20063, 21043 => 39029, 21044 => 25494, 21045 => 19994, 21046 => 21494,
     79821047 => 26355, 21048 => 33099, 21049 => 22812, 21050 => 28082, 21051 => 19968,
     79921052 => 22777, 21053 => 21307, 21054 => 25558, 21055 => 38129, 21056 => 20381,
     80021057 => 20234, 21058 => 34915, 21059 => 39056, 21060 => 22839, 21061 => 36951,
     80121062 => 31227, 21063 => 20202, 21064 => 33008, 21065 => 30097, 21066 => 27778,
     80221067 => 23452, 21068 => 23016, 21069 => 24413, 21070 => 26885, 21071 => 34433,
     80321072 => 20506, 21073 => 24050, 21074 => 20057, 21075 => 30691, 21076 => 20197,
     80421077 => 33402, 21078 => 25233, 21079 => 26131, 21080 => 37009, 21081 => 23673,
     80521082 => 20159, 21083 => 24441, 21084 => 33222, 21085 => 36920, 21086 => 32900,
     80621087 => 30123, 21088 => 20134, 21089 => 35028, 21090 => 24847, 21091 => 27589,
     80721092 => 24518, 21093 => 20041, 21094 => 30410, 21095 => 28322, 21096 => 35811,
     80821097 => 35758, 21098 => 35850, 21099 => 35793, 21100 => 24322, 21101 => 32764,
     80921102 => 32716, 21103 => 32462, 21104 => 33589, 21105 => 33643, 21106 => 22240,
     81021107 => 27575, 21108 => 38899, 21109 => 38452, 21110 => 23035, 21111 => 21535,
     81121112 => 38134, 21113 => 28139, 21114 => 23493, 21115 => 39278, 21116 => 23609,
     81221117 => 24341, 21118 => 38544, 21281 => 21360, 21282 => 33521, 21283 => 27185,
     81321284 => 23156, 21285 => 40560, 21286 => 24212, 21287 => 32552, 21288 => 33721,
     81421289 => 33828, 21290 => 33829, 21291 => 33639, 21292 => 34631, 21293 => 36814,
     81521294 => 36194, 21295 => 30408, 21296 => 24433, 21297 => 39062, 21298 => 30828,
     81621299 => 26144, 21300 => 21727, 21301 => 25317, 21302 => 20323, 21303 => 33219,
     81721304 => 30152, 21305 => 24248, 21306 => 38605, 21307 => 36362, 21308 => 34553,
     81821309 => 21647, 21310 => 27891, 21311 => 28044, 21312 => 27704, 21313 => 24703,
     81921314 => 21191, 21315 => 29992, 21316 => 24189, 21317 => 20248, 21318 => 24736,
     82021319 => 24551, 21320 => 23588, 21321 => 30001, 21322 => 37038, 21323 => 38080,
     82121324 => 29369, 21325 => 27833, 21326 => 28216, 21327 => 37193, 21328 => 26377,
     82221329 => 21451, 21330 => 21491, 21331 => 20305, 21332 => 37321, 21333 => 35825,
     82321334 => 21448, 21335 => 24188, 21336 => 36802, 21337 => 28132, 21338 => 20110,
     82421339 => 30402, 21340 => 27014, 21341 => 34398, 21342 => 24858, 21343 => 33286,
     82521344 => 20313, 21345 => 20446, 21346 => 36926, 21347 => 40060, 21348 => 24841,
     82621349 => 28189, 21350 => 28180, 21351 => 38533, 21352 => 20104, 21353 => 23089,
     82721354 => 38632, 21355 => 19982, 21356 => 23679, 21357 => 31161, 21358 => 23431,
     82821359 => 35821, 21360 => 32701, 21361 => 29577, 21362 => 22495, 21363 => 33419,
     82921364 => 37057, 21365 => 21505, 21366 => 36935, 21367 => 21947, 21368 => 23786,
     83021369 => 24481, 21370 => 24840, 21371 => 27442, 21372 => 29425, 21373 => 32946,
     83121374 => 35465, 21537 => 28020, 21538 => 23507, 21539 => 35029, 21540 => 39044,
     83221541 => 35947, 21542 => 39533, 21543 => 40499, 21544 => 28170, 21545 => 20900,
     83321546 => 20803, 21547 => 22435, 21548 => 34945, 21549 => 21407, 21550 => 25588,
     83421551 => 36757, 21552 => 22253, 21553 => 21592, 21554 => 22278, 21555 => 29503,
     83521556 => 28304, 21557 => 32536, 21558 => 36828, 21559 => 33489, 21560 => 24895,
     83621561 => 24616, 21562 => 38498, 21563 => 26352, 21564 => 32422, 21565 => 36234,
     83721566 => 36291, 21567 => 38053, 21568 => 23731, 21569 => 31908, 21570 => 26376,
     83821571 => 24742, 21572 => 38405, 21573 => 32792, 21574 => 20113, 21575 => 37095,
     83921576 => 21248, 21577 => 38504, 21578 => 20801, 21579 => 36816, 21580 => 34164,
     84021581 => 37213, 21582 => 26197, 21583 => 38901, 21584 => 23381, 21585 => 21277,
     84121586 => 30776, 21587 => 26434, 21588 => 26685, 21589 => 21705, 21590 => 28798,
     84221591 => 23472, 21592 => 36733, 21593 => 20877, 21594 => 22312, 21595 => 21681,
     84321596 => 25874, 21597 => 26242, 21598 => 36190, 21599 => 36163, 21600 => 33039,
     84421601 => 33900, 21602 => 36973, 21603 => 31967, 21604 => 20991, 21605 => 34299,
     84521606 => 26531, 21607 => 26089, 21608 => 28577, 21609 => 34468, 21610 => 36481,
     84621611 => 22122, 21612 => 36896, 21613 => 30338, 21614 => 28790, 21615 => 29157,
     84721616 => 36131, 21617 => 25321, 21618 => 21017, 21619 => 27901, 21620 => 36156,
     84821621 => 24590, 21622 => 22686, 21623 => 24974, 21624 => 26366, 21625 => 36192,
     84921626 => 25166, 21627 => 21939, 21628 => 28195, 21629 => 26413, 21630 => 36711,
     85021793 => 38113, 21794 => 38392, 21795 => 30504, 21796 => 26629, 21797 => 27048,
     85121798 => 21643, 21799 => 20045, 21800 => 28856, 21801 => 35784, 21802 => 25688,
     85221803 => 25995, 21804 => 23429, 21805 => 31364, 21806 => 20538, 21807 => 23528,
     85321808 => 30651, 21809 => 27617, 21810 => 35449, 21811 => 31896, 21812 => 27838,
     85421813 => 30415, 21814 => 26025, 21815 => 36759, 21816 => 23853, 21817 => 23637,
     85521818 => 34360, 21819 => 26632, 21820 => 21344, 21821 => 25112, 21822 => 31449,
     85621823 => 28251, 21824 => 32509, 21825 => 27167, 21826 => 31456, 21827 => 24432,
     85721828 => 28467, 21829 => 24352, 21830 => 25484, 21831 => 28072, 21832 => 26454,
     85821833 => 19976, 21834 => 24080, 21835 => 36134, 21836 => 20183, 21837 => 32960,
     85921838 => 30260, 21839 => 38556, 21840 => 25307, 21841 => 26157, 21842 => 25214,
     86021843 => 27836, 21844 => 36213, 21845 => 29031, 21846 => 32617, 21847 => 20806,
     86121848 => 32903, 21849 => 21484, 21850 => 36974, 21851 => 25240, 21852 => 21746,
     86221853 => 34544, 21854 => 36761, 21855 => 32773, 21856 => 38167, 21857 => 34071,
     86321858 => 36825, 21859 => 27993, 21860 => 29645, 21861 => 26015, 21862 => 30495,
     86421863 => 29956, 21864 => 30759, 21865 => 33275, 21866 => 36126, 21867 => 38024,
     86521868 => 20390, 21869 => 26517, 21870 => 30137, 21871 => 35786, 21872 => 38663,
     86621873 => 25391, 21874 => 38215, 21875 => 38453, 21876 => 33976, 21877 => 25379,
     86721878 => 30529, 21879 => 24449, 21880 => 29424, 21881 => 20105, 21882 => 24596,
     86821883 => 25972, 21884 => 25327, 21885 => 27491, 21886 => 25919, 22049 => 24103,
     86922050 => 30151, 22051 => 37073, 22052 => 35777, 22053 => 33437, 22054 => 26525,
     87022055 => 25903, 22056 => 21553, 22057 => 34584, 22058 => 30693, 22059 => 32930,
     87122060 => 33026, 22061 => 27713, 22062 => 20043, 22063 => 32455, 22064 => 32844,
     87222065 => 30452, 22066 => 26893, 22067 => 27542, 22068 => 25191, 22069 => 20540,
     87322070 => 20356, 22071 => 22336, 22072 => 25351, 22073 => 27490, 22074 => 36286,
     87422075 => 21482, 22076 => 26088, 22077 => 32440, 22078 => 24535, 22079 => 25370,
     87522080 => 25527, 22081 => 33267, 22082 => 33268, 22083 => 32622, 22084 => 24092,
     87622085 => 23769, 22086 => 21046, 22087 => 26234, 22088 => 31209, 22089 => 31258,
     87722090 => 36136, 22091 => 28825, 22092 => 30164, 22093 => 28382, 22094 => 27835,
     87822095 => 31378, 22096 => 20013, 22097 => 30405, 22098 => 24544, 22099 => 38047,
     87922100 => 34935, 22101 => 32456, 22102 => 31181, 22103 => 32959, 22104 => 37325,
     88022105 => 20210, 22106 => 20247, 22107 => 33311, 22108 => 21608, 22109 => 24030,
     88122110 => 27954, 22111 => 35788, 22112 => 31909, 22113 => 36724, 22114 => 32920,
     88222115 => 24090, 22116 => 21650, 22117 => 30385, 22118 => 23449, 22119 => 26172,
     88322120 => 39588, 22121 => 29664, 22122 => 26666, 22123 => 34523, 22124 => 26417,
     88422125 => 29482, 22126 => 35832, 22127 => 35803, 22128 => 36880, 22129 => 31481,
     88522130 => 28891, 22131 => 29038, 22132 => 25284, 22133 => 30633, 22134 => 22065,
     88622135 => 20027, 22136 => 33879, 22137 => 26609, 22138 => 21161, 22139 => 34496,
     88722140 => 36142, 22141 => 38136, 22142 => 31569, 22305 => 20303, 22306 => 27880,
     88822307 => 31069, 22308 => 39547, 22309 => 25235, 22310 => 29226, 22311 => 25341,
     88922312 => 19987, 22313 => 30742, 22314 => 36716, 22315 => 25776, 22316 => 36186,
     89022317 => 31686, 22318 => 26729, 22319 => 24196, 22320 => 35013, 22321 => 22918,
     89122322 => 25758, 22323 => 22766, 22324 => 29366, 22325 => 26894, 22326 => 38181,
     89222327 => 36861, 22328 => 36184, 22329 => 22368, 22330 => 32512, 22331 => 35846,
     89322332 => 20934, 22333 => 25417, 22334 => 25305, 22335 => 21331, 22336 => 26700,
     89422337 => 29730, 22338 => 33537, 22339 => 37196, 22340 => 21828, 22341 => 30528,
     89522342 => 28796, 22343 => 27978, 22344 => 20857, 22345 => 21672, 22346 => 36164,
     89622347 => 23039, 22348 => 28363, 22349 => 28100, 22350 => 23388, 22351 => 32043,
     89722352 => 20180, 22353 => 31869, 22354 => 28371, 22355 => 23376, 22356 => 33258,
     89822357 => 28173, 22358 => 23383, 22359 => 39683, 22360 => 26837, 22361 => 36394,
     89922362 => 23447, 22363 => 32508, 22364 => 24635, 22365 => 32437, 22366 => 37049,
     90022367 => 36208, 22368 => 22863, 22369 => 25549, 22370 => 31199, 22371 => 36275,
     90122372 => 21330, 22373 => 26063, 22374 => 31062, 22375 => 35781, 22376 => 38459,
     90222377 => 32452, 22378 => 38075, 22379 => 32386, 22380 => 22068, 22381 => 37257,
     90322382 => 26368, 22383 => 32618, 22384 => 23562, 22385 => 36981, 22386 => 26152,
     90422387 => 24038, 22388 => 20304, 22389 => 26590, 22390 => 20570, 22391 => 20316,
     90522392 => 22352, 22393 => 24231, 22561 => 20109, 22562 => 19980, 22563 => 20800,
     90622564 => 19984, 22565 => 24319, 22566 => 21317, 22567 => 19989, 22568 => 20120,
     90722569 => 19998, 22570 => 39730, 22571 => 23404, 22572 => 22121, 22573 => 20008,
     90822574 => 31162, 22575 => 20031, 22576 => 21269, 22577 => 20039, 22578 => 22829,
     90922579 => 29243, 22580 => 21358, 22581 => 27664, 22582 => 22239, 22583 => 32996,
     91022584 => 39319, 22585 => 27603, 22586 => 30590, 22587 => 40727, 22588 => 20022,
     91122589 => 20127, 22590 => 40720, 22591 => 20060, 22592 => 20073, 22593 => 20115,
     91222594 => 33416, 22595 => 23387, 22596 => 21868, 22597 => 22031, 22598 => 20164,
     91322599 => 21389, 22600 => 21405, 22601 => 21411, 22602 => 21413, 22603 => 21422,
     91422604 => 38757, 22605 => 36189, 22606 => 21274, 22607 => 21493, 22608 => 21286,
     91522609 => 21294, 22610 => 21310, 22611 => 36188, 22612 => 21350, 22613 => 21347,
     91622614 => 20994, 22615 => 21000, 22616 => 21006, 22617 => 21037, 22618 => 21043,
     91722619 => 21055, 22620 => 21056, 22621 => 21068, 22622 => 21086, 22623 => 21089,
     91822624 => 21084, 22625 => 33967, 22626 => 21117, 22627 => 21122, 22628 => 21121,
     91922629 => 21136, 22630 => 21139, 22631 => 20866, 22632 => 32596, 22633 => 20155,
     92022634 => 20163, 22635 => 20169, 22636 => 20162, 22637 => 20200, 22638 => 20193,
     92122639 => 20203, 22640 => 20190, 22641 => 20251, 22642 => 20211, 22643 => 20258,
     92222644 => 20324, 22645 => 20213, 22646 => 20261, 22647 => 20263, 22648 => 20233,
     92322649 => 20267, 22650 => 20318, 22651 => 20327, 22652 => 25912, 22653 => 20314,
     92422654 => 20317, 22817 => 20319, 22818 => 20311, 22819 => 20274, 22820 => 20285,
     92522821 => 20342, 22822 => 20340, 22823 => 20369, 22824 => 20361, 22825 => 20355,
     92622826 => 20367, 22827 => 20350, 22828 => 20347, 22829 => 20394, 22830 => 20348,
     92722831 => 20396, 22832 => 20372, 22833 => 20454, 22834 => 20456, 22835 => 20458,
     92822836 => 20421, 22837 => 20442, 22838 => 20451, 22839 => 20444, 22840 => 20433,
     92922841 => 20447, 22842 => 20472, 22843 => 20521, 22844 => 20556, 22845 => 20467,
     93022846 => 20524, 22847 => 20495, 22848 => 20526, 22849 => 20525, 22850 => 20478,
     93122851 => 20508, 22852 => 20492, 22853 => 20517, 22854 => 20520, 22855 => 20606,
     93222856 => 20547, 22857 => 20565, 22858 => 20552, 22859 => 20558, 22860 => 20588,
     93322861 => 20603, 22862 => 20645, 22863 => 20647, 22864 => 20649, 22865 => 20666,
     93422866 => 20694, 22867 => 20742, 22868 => 20717, 22869 => 20716, 22870 => 20710,
     93522871 => 20718, 22872 => 20743, 22873 => 20747, 22874 => 20189, 22875 => 27709,
     93622876 => 20312, 22877 => 20325, 22878 => 20430, 22879 => 40864, 22880 => 27718,
     93722881 => 31860, 22882 => 20846, 22883 => 24061, 22884 => 40649, 22885 => 39320,
     93822886 => 20865, 22887 => 22804, 22888 => 21241, 22889 => 21261, 22890 => 35335,
     93922891 => 21264, 22892 => 20971, 22893 => 22809, 22894 => 20821, 22895 => 20128,
     94022896 => 20822, 22897 => 20147, 22898 => 34926, 22899 => 34980, 22900 => 20149,
     94122901 => 33044, 22902 => 35026, 22903 => 31104, 22904 => 23348, 22905 => 34819,
     94222906 => 32696, 22907 => 20907, 22908 => 20913, 22909 => 20925, 22910 => 20924,
     94323073 => 20935, 23074 => 20886, 23075 => 20898, 23076 => 20901, 23077 => 35744,
     94423078 => 35750, 23079 => 35751, 23080 => 35754, 23081 => 35764, 23082 => 35765,
     94523083 => 35767, 23084 => 35778, 23085 => 35779, 23086 => 35787, 23087 => 35791,
     94623088 => 35790, 23089 => 35794, 23090 => 35795, 23091 => 35796, 23092 => 35798,
     94723093 => 35800, 23094 => 35801, 23095 => 35804, 23096 => 35807, 23097 => 35808,
     94823098 => 35812, 23099 => 35816, 23100 => 35817, 23101 => 35822, 23102 => 35824,
     94923103 => 35827, 23104 => 35830, 23105 => 35833, 23106 => 35836, 23107 => 35839,
     95023108 => 35840, 23109 => 35842, 23110 => 35844, 23111 => 35847, 23112 => 35852,
     95123113 => 35855, 23114 => 35857, 23115 => 35858, 23116 => 35860, 23117 => 35861,
     95223118 => 35862, 23119 => 35865, 23120 => 35867, 23121 => 35864, 23122 => 35869,
     95323123 => 35871, 23124 => 35872, 23125 => 35873, 23126 => 35877, 23127 => 35879,
     95423128 => 35882, 23129 => 35883, 23130 => 35886, 23131 => 35887, 23132 => 35890,
     95523133 => 35891, 23134 => 35893, 23135 => 35894, 23136 => 21353, 23137 => 21370,
     95623138 => 38429, 23139 => 38434, 23140 => 38433, 23141 => 38449, 23142 => 38442,
     95723143 => 38461, 23144 => 38460, 23145 => 38466, 23146 => 38473, 23147 => 38484,
     95823148 => 38495, 23149 => 38503, 23150 => 38508, 23151 => 38514, 23152 => 38516,
     95923153 => 38536, 23154 => 38541, 23155 => 38551, 23156 => 38576, 23157 => 37015,
     96023158 => 37019, 23159 => 37021, 23160 => 37017, 23161 => 37036, 23162 => 37025,
     96123163 => 37044, 23164 => 37043, 23165 => 37046, 23166 => 37050, 23329 => 37048,
     96223330 => 37040, 23331 => 37071, 23332 => 37061, 23333 => 37054, 23334 => 37072,
     96323335 => 37060, 23336 => 37063, 23337 => 37075, 23338 => 37094, 23339 => 37090,
     96423340 => 37084, 23341 => 37079, 23342 => 37083, 23343 => 37099, 23344 => 37103,
     96523345 => 37118, 23346 => 37124, 23347 => 37154, 23348 => 37150, 23349 => 37155,
     96623350 => 37169, 23351 => 37167, 23352 => 37177, 23353 => 37187, 23354 => 37190,
     96723355 => 21005, 23356 => 22850, 23357 => 21154, 23358 => 21164, 23359 => 21165,
     96823360 => 21182, 23361 => 21759, 23362 => 21200, 23363 => 21206, 23364 => 21232,
     96923365 => 21471, 23366 => 29166, 23367 => 30669, 23368 => 24308, 23369 => 20981,
     97023370 => 20988, 23371 => 39727, 23372 => 21430, 23373 => 24321, 23374 => 30042,
     97123375 => 24047, 23376 => 22348, 23377 => 22441, 23378 => 22433, 23379 => 22654,
     97223380 => 22716, 23381 => 22725, 23382 => 22737, 23383 => 22313, 23384 => 22316,
     97323385 => 22314, 23386 => 22323, 23387 => 22329, 23388 => 22318, 23389 => 22319,
     97423390 => 22364, 23391 => 22331, 23392 => 22338, 23393 => 22377, 23394 => 22405,
     97523395 => 22379, 23396 => 22406, 23397 => 22396, 23398 => 22395, 23399 => 22376,
     97623400 => 22381, 23401 => 22390, 23402 => 22387, 23403 => 22445, 23404 => 22436,
     97723405 => 22412, 23406 => 22450, 23407 => 22479, 23408 => 22439, 23409 => 22452,
     97823410 => 22419, 23411 => 22432, 23412 => 22485, 23413 => 22488, 23414 => 22490,
     97923415 => 22489, 23416 => 22482, 23417 => 22456, 23418 => 22516, 23419 => 22511,
     98023420 => 22520, 23421 => 22500, 23422 => 22493, 23585 => 22539, 23586 => 22541,
     98123587 => 22525, 23588 => 22509, 23589 => 22528, 23590 => 22558, 23591 => 22553,
     98223592 => 22596, 23593 => 22560, 23594 => 22629, 23595 => 22636, 23596 => 22657,
     98323597 => 22665, 23598 => 22682, 23599 => 22656, 23600 => 39336, 23601 => 40729,
     98423602 => 25087, 23603 => 33401, 23604 => 33405, 23605 => 33407, 23606 => 33423,
     98523607 => 33418, 23608 => 33448, 23609 => 33412, 23610 => 33422, 23611 => 33425,
     98623612 => 33431, 23613 => 33433, 23614 => 33451, 23615 => 33464, 23616 => 33470,
     98723617 => 33456, 23618 => 33480, 23619 => 33482, 23620 => 33507, 23621 => 33432,
     98823622 => 33463, 23623 => 33454, 23624 => 33483, 23625 => 33484, 23626 => 33473,
     98923627 => 33449, 23628 => 33460, 23629 => 33441, 23630 => 33450, 23631 => 33439,
     99023632 => 33476, 23633 => 33486, 23634 => 33444, 23635 => 33505, 23636 => 33545,
     99123637 => 33527, 23638 => 33508, 23639 => 33551, 23640 => 33543, 23641 => 33500,
     99223642 => 33524, 23643 => 33490, 23644 => 33496, 23645 => 33548, 23646 => 33531,
     99323647 => 33491, 23648 => 33553, 23649 => 33562, 23650 => 33542, 23651 => 33556,
     99423652 => 33557, 23653 => 33504, 23654 => 33493, 23655 => 33564, 23656 => 33617,
     99523657 => 33627, 23658 => 33628, 23659 => 33544, 23660 => 33682, 23661 => 33596,
     99623662 => 33588, 23663 => 33585, 23664 => 33691, 23665 => 33630, 23666 => 33583,
     99723667 => 33615, 23668 => 33607, 23669 => 33603, 23670 => 33631, 23671 => 33600,
     99823672 => 33559, 23673 => 33632, 23674 => 33581, 23675 => 33594, 23676 => 33587,
     99923677 => 33638, 23678 => 33637, 23841 => 33640, 23842 => 33563, 23843 => 33641,
     100023844 => 33644, 23845 => 33642, 23846 => 33645, 23847 => 33646, 23848 => 33712,
     100123849 => 33656, 23850 => 33715, 23851 => 33716, 23852 => 33696, 23853 => 33706,
     100223854 => 33683, 23855 => 33692, 23856 => 33669, 23857 => 33660, 23858 => 33718,
     100323859 => 33705, 23860 => 33661, 23861 => 33720, 23862 => 33659, 23863 => 33688,
     100423864 => 33694, 23865 => 33704, 23866 => 33722, 23867 => 33724, 23868 => 33729,
     100523869 => 33793, 23870 => 33765, 23871 => 33752, 23872 => 22535, 23873 => 33816,
     100623874 => 33803, 23875 => 33757, 23876 => 33789, 23877 => 33750, 23878 => 33820,
     100723879 => 33848, 23880 => 33809, 23881 => 33798, 23882 => 33748, 23883 => 33759,
     100823884 => 33807, 23885 => 33795, 23886 => 33784, 23887 => 33785, 23888 => 33770,
     100923889 => 33733, 23890 => 33728, 23891 => 33830, 23892 => 33776, 23893 => 33761,
     101023894 => 33884, 23895 => 33873, 23896 => 33882, 23897 => 33881, 23898 => 33907,
     101123899 => 33927, 23900 => 33928, 23901 => 33914, 23902 => 33929, 23903 => 33912,
     101223904 => 33852, 23905 => 33862, 23906 => 33897, 23907 => 33910, 23908 => 33932,
     101323909 => 33934, 23910 => 33841, 23911 => 33901, 23912 => 33985, 23913 => 33997,
     101423914 => 34000, 23915 => 34022, 23916 => 33981, 23917 => 34003, 23918 => 33994,
     101523919 => 33983, 23920 => 33978, 23921 => 34016, 23922 => 33953, 23923 => 33977,
     101623924 => 33972, 23925 => 33943, 23926 => 34021, 23927 => 34019, 23928 => 34060,
     101723929 => 29965, 23930 => 34104, 23931 => 34032, 23932 => 34105, 23933 => 34079,
     101823934 => 34106, 24097 => 34134, 24098 => 34107, 24099 => 34047, 24100 => 34044,
     101924101 => 34137, 24102 => 34120, 24103 => 34152, 24104 => 34148, 24105 => 34142,
     102024106 => 34170, 24107 => 30626, 24108 => 34115, 24109 => 34162, 24110 => 34171,
     102124111 => 34212, 24112 => 34216, 24113 => 34183, 24114 => 34191, 24115 => 34169,
     102224116 => 34222, 24117 => 34204, 24118 => 34181, 24119 => 34233, 24120 => 34231,
     102324121 => 34224, 24122 => 34259, 24123 => 34241, 24124 => 34268, 24125 => 34303,
     102424126 => 34343, 24127 => 34309, 24128 => 34345, 24129 => 34326, 24130 => 34364,
     102524131 => 24318, 24132 => 24328, 24133 => 22844, 24134 => 22849, 24135 => 32823,
     102624136 => 22869, 24137 => 22874, 24138 => 22872, 24139 => 21263, 24140 => 23586,
     102724141 => 23589, 24142 => 23596, 24143 => 23604, 24144 => 25164, 24145 => 25194,
     102824146 => 25247, 24147 => 25275, 24148 => 25290, 24149 => 25306, 24150 => 25303,
     102924151 => 25326, 24152 => 25378, 24153 => 25334, 24154 => 25401, 24155 => 25419,
     103024156 => 25411, 24157 => 25517, 24158 => 25590, 24159 => 25457, 24160 => 25466,
     103124161 => 25486, 24162 => 25524, 24163 => 25453, 24164 => 25516, 24165 => 25482,
     103224166 => 25449, 24167 => 25518, 24168 => 25532, 24169 => 25586, 24170 => 25592,
     103324171 => 25568, 24172 => 25599, 24173 => 25540, 24174 => 25566, 24175 => 25550,
     103424176 => 25682, 24177 => 25542, 24178 => 25534, 24179 => 25669, 24180 => 25665,
     103524181 => 25611, 24182 => 25627, 24183 => 25632, 24184 => 25612, 24185 => 25638,
     103624186 => 25633, 24187 => 25694, 24188 => 25732, 24189 => 25709, 24190 => 25750,
     103724353 => 25722, 24354 => 25783, 24355 => 25784, 24356 => 25753, 24357 => 25786,
     103824358 => 25792, 24359 => 25808, 24360 => 25815, 24361 => 25828, 24362 => 25826,
     103924363 => 25865, 24364 => 25893, 24365 => 25902, 24366 => 24331, 24367 => 24530,
     104024368 => 29977, 24369 => 24337, 24370 => 21343, 24371 => 21489, 24372 => 21501,
     104124373 => 21481, 24374 => 21480, 24375 => 21499, 24376 => 21522, 24377 => 21526,
     104224378 => 21510, 24379 => 21579, 24380 => 21586, 24381 => 21587, 24382 => 21588,
     104324383 => 21590, 24384 => 21571, 24385 => 21537, 24386 => 21591, 24387 => 21593,
     104424388 => 21539, 24389 => 21554, 24390 => 21634, 24391 => 21652, 24392 => 21623,
     104524393 => 21617, 24394 => 21604, 24395 => 21658, 24396 => 21659, 24397 => 21636,
     104624398 => 21622, 24399 => 21606, 24400 => 21661, 24401 => 21712, 24402 => 21677,
     104724403 => 21698, 24404 => 21684, 24405 => 21714, 24406 => 21671, 24407 => 21670,
     104824408 => 21715, 24409 => 21716, 24410 => 21618, 24411 => 21667, 24412 => 21717,
     104924413 => 21691, 24414 => 21695, 24415 => 21708, 24416 => 21721, 24417 => 21722,
     105024418 => 21724, 24419 => 21673, 24420 => 21674, 24421 => 21668, 24422 => 21725,
     105124423 => 21711, 24424 => 21726, 24425 => 21787, 24426 => 21735, 24427 => 21792,
     105224428 => 21757, 24429 => 21780, 24430 => 21747, 24431 => 21794, 24432 => 21795,
     105324433 => 21775, 24434 => 21777, 24435 => 21799, 24436 => 21802, 24437 => 21863,
     105424438 => 21903, 24439 => 21941, 24440 => 21833, 24441 => 21869, 24442 => 21825,
     105524443 => 21845, 24444 => 21823, 24445 => 21840, 24446 => 21820, 24609 => 21815,
     105624610 => 21846, 24611 => 21877, 24612 => 21878, 24613 => 21879, 24614 => 21811,
     105724615 => 21808, 24616 => 21852, 24617 => 21899, 24618 => 21970, 24619 => 21891,
     105824620 => 21937, 24621 => 21945, 24622 => 21896, 24623 => 21889, 24624 => 21919,
     105924625 => 21886, 24626 => 21974, 24627 => 21905, 24628 => 21883, 24629 => 21983,
     106024630 => 21949, 24631 => 21950, 24632 => 21908, 24633 => 21913, 24634 => 21994,
     106124635 => 22007, 24636 => 21961, 24637 => 22047, 24638 => 21969, 24639 => 21995,
     106224640 => 21996, 24641 => 21972, 24642 => 21990, 24643 => 21981, 24644 => 21956,
     106324645 => 21999, 24646 => 21989, 24647 => 22002, 24648 => 22003, 24649 => 21964,
     106424650 => 21965, 24651 => 21992, 24652 => 22005, 24653 => 21988, 24654 => 36756,
     106524655 => 22046, 24656 => 22024, 24657 => 22028, 24658 => 22017, 24659 => 22052,
     106624660 => 22051, 24661 => 22014, 24662 => 22016, 24663 => 22055, 24664 => 22061,
     106724665 => 22104, 24666 => 22073, 24667 => 22103, 24668 => 22060, 24669 => 22093,
     106824670 => 22114, 24671 => 22105, 24672 => 22108, 24673 => 22092, 24674 => 22100,
     106924675 => 22150, 24676 => 22116, 24677 => 22129, 24678 => 22123, 24679 => 22139,
     107024680 => 22140, 24681 => 22149, 24682 => 22163, 24683 => 22191, 24684 => 22228,
     107124685 => 22231, 24686 => 22237, 24687 => 22241, 24688 => 22261, 24689 => 22251,
     107224690 => 22265, 24691 => 22271, 24692 => 22276, 24693 => 22282, 24694 => 22281,
     107324695 => 22300, 24696 => 24079, 24697 => 24089, 24698 => 24084, 24699 => 24081,
     107424700 => 24113, 24701 => 24123, 24702 => 24124, 24865 => 24119, 24866 => 24132,
     107524867 => 24148, 24868 => 24155, 24869 => 24158, 24870 => 24161, 24871 => 23692,
     107624872 => 23674, 24873 => 23693, 24874 => 23696, 24875 => 23702, 24876 => 23688,
     107724877 => 23704, 24878 => 23705, 24879 => 23697, 24880 => 23706, 24881 => 23708,
     107824882 => 23733, 24883 => 23714, 24884 => 23741, 24885 => 23724, 24886 => 23723,
     107924887 => 23729, 24888 => 23715, 24889 => 23745, 24890 => 23735, 24891 => 23748,
     108024892 => 23762, 24893 => 23780, 24894 => 23755, 24895 => 23781, 24896 => 23810,
     108124897 => 23811, 24898 => 23847, 24899 => 23846, 24900 => 23854, 24901 => 23844,
     108224902 => 23838, 24903 => 23814, 24904 => 23835, 24905 => 23896, 24906 => 23870,
     108324907 => 23860, 24908 => 23869, 24909 => 23916, 24910 => 23899, 24911 => 23919,
     108424912 => 23901, 24913 => 23915, 24914 => 23883, 24915 => 23882, 24916 => 23913,
     108524917 => 23924, 24918 => 23938, 24919 => 23961, 24920 => 23965, 24921 => 35955,
     108624922 => 23991, 24923 => 24005, 24924 => 24435, 24925 => 24439, 24926 => 24450,
     108724927 => 24455, 24928 => 24457, 24929 => 24460, 24930 => 24469, 24931 => 24473,
     108824932 => 24476, 24933 => 24488, 24934 => 24493, 24935 => 24501, 24936 => 24508,
     108924937 => 34914, 24938 => 24417, 24939 => 29357, 24940 => 29360, 24941 => 29364,
     109024942 => 29367, 24943 => 29368, 24944 => 29379, 24945 => 29377, 24946 => 29390,
     109124947 => 29389, 24948 => 29394, 24949 => 29416, 24950 => 29423, 24951 => 29417,
     109224952 => 29426, 24953 => 29428, 24954 => 29431, 24955 => 29441, 24956 => 29427,
     109324957 => 29443, 24958 => 29434, 25121 => 29435, 25122 => 29463, 25123 => 29459,
     109425124 => 29473, 25125 => 29450, 25126 => 29470, 25127 => 29469, 25128 => 29461,
     109525129 => 29474, 25130 => 29497, 25131 => 29477, 25132 => 29484, 25133 => 29496,
     109625134 => 29489, 25135 => 29520, 25136 => 29517, 25137 => 29527, 25138 => 29536,
     109725139 => 29548, 25140 => 29551, 25141 => 29566, 25142 => 33307, 25143 => 22821,
     109825144 => 39143, 25145 => 22820, 25146 => 22786, 25147 => 39267, 25148 => 39271,
     109925149 => 39272, 25150 => 39273, 25151 => 39274, 25152 => 39275, 25153 => 39276,
     110025154 => 39284, 25155 => 39287, 25156 => 39293, 25157 => 39296, 25158 => 39300,
     110125159 => 39303, 25160 => 39306, 25161 => 39309, 25162 => 39312, 25163 => 39313,
     110225164 => 39315, 25165 => 39316, 25166 => 39317, 25167 => 24192, 25168 => 24209,
     110325169 => 24203, 25170 => 24214, 25171 => 24229, 25172 => 24224, 25173 => 24249,
     110425174 => 24245, 25175 => 24254, 25176 => 24243, 25177 => 36179, 25178 => 24274,
     110525179 => 24273, 25180 => 24283, 25181 => 24296, 25182 => 24298, 25183 => 33210,
     110625184 => 24516, 25185 => 24521, 25186 => 24534, 25187 => 24527, 25188 => 24579,
     110725189 => 24558, 25190 => 24580, 25191 => 24545, 25192 => 24548, 25193 => 24574,
     110825194 => 24581, 25195 => 24582, 25196 => 24554, 25197 => 24557, 25198 => 24568,
     110925199 => 24601, 25200 => 24629, 25201 => 24614, 25202 => 24603, 25203 => 24591,
     111025204 => 24589, 25205 => 24617, 25206 => 24619, 25207 => 24586, 25208 => 24639,
     111125209 => 24609, 25210 => 24696, 25211 => 24697, 25212 => 24699, 25213 => 24698,
     111225214 => 24642, 25377 => 24682, 25378 => 24701, 25379 => 24726, 25380 => 24730,
     111325381 => 24749, 25382 => 24733, 25383 => 24707, 25384 => 24722, 25385 => 24716,
     111425386 => 24731, 25387 => 24812, 25388 => 24763, 25389 => 24753, 25390 => 24797,
     111525391 => 24792, 25392 => 24774, 25393 => 24794, 25394 => 24756, 25395 => 24864,
     111625396 => 24870, 25397 => 24853, 25398 => 24867, 25399 => 24820, 25400 => 24832,
     111725401 => 24846, 25402 => 24875, 25403 => 24906, 25404 => 24949, 25405 => 25004,
     111825406 => 24980, 25407 => 24999, 25408 => 25015, 25409 => 25044, 25410 => 25077,
     111925411 => 24541, 25412 => 38579, 25413 => 38377, 25414 => 38379, 25415 => 38385,
     112025416 => 38387, 25417 => 38389, 25418 => 38390, 25419 => 38396, 25420 => 38398,
     112125421 => 38403, 25422 => 38404, 25423 => 38406, 25424 => 38408, 25425 => 38410,
     112225426 => 38411, 25427 => 38412, 25428 => 38413, 25429 => 38415, 25430 => 38418,
     112325431 => 38421, 25432 => 38422, 25433 => 38423, 25434 => 38425, 25435 => 38426,
     112425436 => 20012, 25437 => 29247, 25438 => 25109, 25439 => 27701, 25440 => 27732,
     112525441 => 27740, 25442 => 27722, 25443 => 27811, 25444 => 27781, 25445 => 27792,
     112625446 => 27796, 25447 => 27788, 25448 => 27752, 25449 => 27753, 25450 => 27764,
     112725451 => 27766, 25452 => 27782, 25453 => 27817, 25454 => 27856, 25455 => 27860,
     112825456 => 27821, 25457 => 27895, 25458 => 27896, 25459 => 27889, 25460 => 27863,
     112925461 => 27826, 25462 => 27872, 25463 => 27862, 25464 => 27898, 25465 => 27883,
     113025466 => 27886, 25467 => 27825, 25468 => 27859, 25469 => 27887, 25470 => 27902,
     113125633 => 27961, 25634 => 27943, 25635 => 27916, 25636 => 27971, 25637 => 27976,
     113225638 => 27911, 25639 => 27908, 25640 => 27929, 25641 => 27918, 25642 => 27947,
     113325643 => 27981, 25644 => 27950, 25645 => 27957, 25646 => 27930, 25647 => 27983,
     113425648 => 27986, 25649 => 27988, 25650 => 27955, 25651 => 28049, 25652 => 28015,
     113525653 => 28062, 25654 => 28064, 25655 => 27998, 25656 => 28051, 25657 => 28052,
     113625658 => 27996, 25659 => 28000, 25660 => 28028, 25661 => 28003, 25662 => 28186,
     113725663 => 28103, 25664 => 28101, 25665 => 28126, 25666 => 28174, 25667 => 28095,
     113825668 => 28128, 25669 => 28177, 25670 => 28134, 25671 => 28125, 25672 => 28121,
     113925673 => 28182, 25674 => 28075, 25675 => 28172, 25676 => 28078, 25677 => 28203,
     114025678 => 28270, 25679 => 28238, 25680 => 28267, 25681 => 28338, 25682 => 28255,
     114125683 => 28294, 25684 => 28243, 25685 => 28244, 25686 => 28210, 25687 => 28197,
     114225688 => 28228, 25689 => 28383, 25690 => 28337, 25691 => 28312, 25692 => 28384,
     114325693 => 28461, 25694 => 28386, 25695 => 28325, 25696 => 28327, 25697 => 28349,
     114425698 => 28347, 25699 => 28343, 25700 => 28375, 25701 => 28340, 25702 => 28367,
     114525703 => 28303, 25704 => 28354, 25705 => 28319, 25706 => 28514, 25707 => 28486,
     114625708 => 28487, 25709 => 28452, 25710 => 28437, 25711 => 28409, 25712 => 28463,
     114725713 => 28470, 25714 => 28491, 25715 => 28532, 25716 => 28458, 25717 => 28425,
     114825718 => 28457, 25719 => 28553, 25720 => 28557, 25721 => 28556, 25722 => 28536,
     114925723 => 28530, 25724 => 28540, 25725 => 28538, 25726 => 28625, 25889 => 28617,
     115025890 => 28583, 25891 => 28601, 25892 => 28598, 25893 => 28610, 25894 => 28641,
     115125895 => 28654, 25896 => 28638, 25897 => 28640, 25898 => 28655, 25899 => 28698,
     115225900 => 28707, 25901 => 28699, 25902 => 28729, 25903 => 28725, 25904 => 28751,
     115325905 => 28766, 25906 => 23424, 25907 => 23428, 25908 => 23445, 25909 => 23443,
     115425910 => 23461, 25911 => 23480, 25912 => 29999, 25913 => 39582, 25914 => 25652,
     115525915 => 23524, 25916 => 23534, 25917 => 35120, 25918 => 23536, 25919 => 36423,
     115625920 => 35591, 25921 => 36790, 25922 => 36819, 25923 => 36821, 25924 => 36837,
     115725925 => 36846, 25926 => 36836, 25927 => 36841, 25928 => 36838, 25929 => 36851,
     115825930 => 36840, 25931 => 36869, 25932 => 36868, 25933 => 36875, 25934 => 36902,
     115925935 => 36881, 25936 => 36877, 25937 => 36886, 25938 => 36897, 25939 => 36917,
     116025940 => 36918, 25941 => 36909, 25942 => 36911, 25943 => 36932, 25944 => 36945,
     116125945 => 36946, 25946 => 36944, 25947 => 36968, 25948 => 36952, 25949 => 36962,
     116225950 => 36955, 25951 => 26297, 25952 => 36980, 25953 => 36989, 25954 => 36994,
     116325955 => 37000, 25956 => 36995, 25957 => 37003, 25958 => 24400, 25959 => 24407,
     116425960 => 24406, 25961 => 24408, 25962 => 23611, 25963 => 21675, 25964 => 23632,
     116525965 => 23641, 25966 => 23409, 25967 => 23651, 25968 => 23654, 25969 => 32700,
     116625970 => 24362, 25971 => 24361, 25972 => 24365, 25973 => 33396, 25974 => 24380,
     116725975 => 39739, 25976 => 23662, 25977 => 22913, 25978 => 22915, 25979 => 22925,
     116825980 => 22953, 25981 => 22954, 25982 => 22947, 26145 => 22935, 26146 => 22986,
     116926147 => 22955, 26148 => 22942, 26149 => 22948, 26150 => 22994, 26151 => 22962,
     117026152 => 22959, 26153 => 22999, 26154 => 22974, 26155 => 23045, 26156 => 23046,
     117126157 => 23005, 26158 => 23048, 26159 => 23011, 26160 => 23000, 26161 => 23033,
     117226162 => 23052, 26163 => 23049, 26164 => 23090, 26165 => 23092, 26166 => 23057,
     117326167 => 23075, 26168 => 23059, 26169 => 23104, 26170 => 23143, 26171 => 23114,
     117426172 => 23125, 26173 => 23100, 26174 => 23138, 26175 => 23157, 26176 => 33004,
     117526177 => 23210, 26178 => 23195, 26179 => 23159, 26180 => 23162, 26181 => 23230,
     117626182 => 23275, 26183 => 23218, 26184 => 23250, 26185 => 23252, 26186 => 23224,
     117726187 => 23264, 26188 => 23267, 26189 => 23281, 26190 => 23254, 26191 => 23270,
     117826192 => 23256, 26193 => 23260, 26194 => 23305, 26195 => 23319, 26196 => 23318,
     117926197 => 23346, 26198 => 23351, 26199 => 23360, 26200 => 23573, 26201 => 23580,
     118026202 => 23386, 26203 => 23397, 26204 => 23411, 26205 => 23377, 26206 => 23379,
     118126207 => 23394, 26208 => 39541, 26209 => 39543, 26210 => 39544, 26211 => 39546,
     118226212 => 39551, 26213 => 39549, 26214 => 39552, 26215 => 39553, 26216 => 39557,
     118326217 => 39560, 26218 => 39562, 26219 => 39568, 26220 => 39570, 26221 => 39571,
     118426222 => 39574, 26223 => 39576, 26224 => 39579, 26225 => 39580, 26226 => 39581,
     118526227 => 39583, 26228 => 39584, 26229 => 39586, 26230 => 39587, 26231 => 39589,
     118626232 => 39591, 26233 => 32415, 26234 => 32417, 26235 => 32419, 26236 => 32421,
     118726237 => 32424, 26238 => 32425, 26401 => 32429, 26402 => 32432, 26403 => 32446,
     118826404 => 32448, 26405 => 32449, 26406 => 32450, 26407 => 32457, 26408 => 32459,
     118926409 => 32460, 26410 => 32464, 26411 => 32468, 26412 => 32471, 26413 => 32475,
     119026414 => 32480, 26415 => 32481, 26416 => 32488, 26417 => 32491, 26418 => 32494,
     119126419 => 32495, 26420 => 32497, 26421 => 32498, 26422 => 32525, 26423 => 32502,
     119226424 => 32506, 26425 => 32507, 26426 => 32510, 26427 => 32513, 26428 => 32514,
     119326429 => 32515, 26430 => 32519, 26431 => 32520, 26432 => 32523, 26433 => 32524,
     119426434 => 32527, 26435 => 32529, 26436 => 32530, 26437 => 32535, 26438 => 32537,
     119526439 => 32540, 26440 => 32539, 26441 => 32543, 26442 => 32545, 26443 => 32546,
     119626444 => 32547, 26445 => 32548, 26446 => 32549, 26447 => 32550, 26448 => 32551,
     119726449 => 32554, 26450 => 32555, 26451 => 32556, 26452 => 32557, 26453 => 32559,
     119826454 => 32560, 26455 => 32561, 26456 => 32562, 26457 => 32563, 26458 => 32565,
     119926459 => 24186, 26460 => 30079, 26461 => 24027, 26462 => 30014, 26463 => 37013,
     120026464 => 29582, 26465 => 29585, 26466 => 29614, 26467 => 29602, 26468 => 29599,
     120126469 => 29647, 26470 => 29634, 26471 => 29649, 26472 => 29623, 26473 => 29619,
     120226474 => 29632, 26475 => 29641, 26476 => 29640, 26477 => 29669, 26478 => 29657,
     120326479 => 39036, 26480 => 29706, 26481 => 29673, 26482 => 29671, 26483 => 29662,
     120426484 => 29626, 26485 => 29682, 26486 => 29711, 26487 => 29738, 26488 => 29787,
     120526489 => 29734, 26490 => 29733, 26491 => 29736, 26492 => 29744, 26493 => 29742,
     120626494 => 29740, 26657 => 29723, 26658 => 29722, 26659 => 29761, 26660 => 29788,
     120726661 => 29783, 26662 => 29781, 26663 => 29785, 26664 => 29815, 26665 => 29805,
     120826666 => 29822, 26667 => 29852, 26668 => 29838, 26669 => 29824, 26670 => 29825,
     120926671 => 29831, 26672 => 29835, 26673 => 29854, 26674 => 29864, 26675 => 29865,
     121026676 => 29840, 26677 => 29863, 26678 => 29906, 26679 => 29882, 26680 => 38890,
     121126681 => 38891, 26682 => 38892, 26683 => 26444, 26684 => 26451, 26685 => 26462,
     121226686 => 26440, 26687 => 26473, 26688 => 26533, 26689 => 26503, 26690 => 26474,
     121326691 => 26483, 26692 => 26520, 26693 => 26535, 26694 => 26485, 26695 => 26536,
     121426696 => 26526, 26697 => 26541, 26698 => 26507, 26699 => 26487, 26700 => 26492,
     121526701 => 26608, 26702 => 26633, 26703 => 26584, 26704 => 26634, 26705 => 26601,
     121626706 => 26544, 26707 => 26636, 26708 => 26585, 26709 => 26549, 26710 => 26586,
     121726711 => 26547, 26712 => 26589, 26713 => 26624, 26714 => 26563, 26715 => 26552,
     121826716 => 26594, 26717 => 26638, 26718 => 26561, 26719 => 26621, 26720 => 26674,
     121926721 => 26675, 26722 => 26720, 26723 => 26721, 26724 => 26702, 26725 => 26722,
     122026726 => 26692, 26727 => 26724, 26728 => 26755, 26729 => 26653, 26730 => 26709,
     122126731 => 26726, 26732 => 26689, 26733 => 26727, 26734 => 26688, 26735 => 26686,
     122226736 => 26698, 26737 => 26697, 26738 => 26665, 26739 => 26805, 26740 => 26767,
     122326741 => 26740, 26742 => 26743, 26743 => 26771, 26744 => 26731, 26745 => 26818,
     122426746 => 26990, 26747 => 26876, 26748 => 26911, 26749 => 26912, 26750 => 26873,
     122526913 => 26916, 26914 => 26864, 26915 => 26891, 26916 => 26881, 26917 => 26967,
     122626918 => 26851, 26919 => 26896, 26920 => 26993, 26921 => 26937, 26922 => 26976,
     122726923 => 26946, 26924 => 26973, 26925 => 27012, 26926 => 26987, 26927 => 27008,
     122826928 => 27032, 26929 => 27000, 26930 => 26932, 26931 => 27084, 26932 => 27015,
     122926933 => 27016, 26934 => 27086, 26935 => 27017, 26936 => 26982, 26937 => 26979,
     123026938 => 27001, 26939 => 27035, 26940 => 27047, 26941 => 27067, 26942 => 27051,
     123126943 => 27053, 26944 => 27092, 26945 => 27057, 26946 => 27073, 26947 => 27082,
     123226948 => 27103, 26949 => 27029, 26950 => 27104, 26951 => 27021, 26952 => 27135,
     123326953 => 27183, 26954 => 27117, 26955 => 27159, 26956 => 27160, 26957 => 27237,
     123426958 => 27122, 26959 => 27204, 26960 => 27198, 26961 => 27296, 26962 => 27216,
     123526963 => 27227, 26964 => 27189, 26965 => 27278, 26966 => 27257, 26967 => 27197,
     123626968 => 27176, 26969 => 27224, 26970 => 27260, 26971 => 27281, 26972 => 27280,
     123726973 => 27305, 26974 => 27287, 26975 => 27307, 26976 => 29495, 26977 => 29522,
     123826978 => 27521, 26979 => 27522, 26980 => 27527, 26981 => 27524, 26982 => 27538,
     123926983 => 27539, 26984 => 27533, 26985 => 27546, 26986 => 27547, 26987 => 27553,
     124026988 => 27562, 26989 => 36715, 26990 => 36717, 26991 => 36721, 26992 => 36722,
     124126993 => 36723, 26994 => 36725, 26995 => 36726, 26996 => 36728, 26997 => 36727,
     124226998 => 36729, 26999 => 36730, 27000 => 36732, 27001 => 36734, 27002 => 36737,
     124327003 => 36738, 27004 => 36740, 27005 => 36743, 27006 => 36747, 27169 => 36749,
     124427170 => 36750, 27171 => 36751, 27172 => 36760, 27173 => 36762, 27174 => 36558,
     124527175 => 25099, 27176 => 25111, 27177 => 25115, 27178 => 25119, 27179 => 25122,
     124627180 => 25121, 27181 => 25125, 27182 => 25124, 27183 => 25132, 27184 => 33255,
     124727185 => 29935, 27186 => 29940, 27187 => 29951, 27188 => 29967, 27189 => 29969,
     124827190 => 29971, 27191 => 25908, 27192 => 26094, 27193 => 26095, 27194 => 26096,
     124927195 => 26122, 27196 => 26137, 27197 => 26482, 27198 => 26115, 27199 => 26133,
     125027200 => 26112, 27201 => 28805, 27202 => 26359, 27203 => 26141, 27204 => 26164,
     125127205 => 26161, 27206 => 26166, 27207 => 26165, 27208 => 32774, 27209 => 26207,
     125227210 => 26196, 27211 => 26177, 27212 => 26191, 27213 => 26198, 27214 => 26209,
     125327215 => 26199, 27216 => 26231, 27217 => 26244, 27218 => 26252, 27219 => 26279,
     125427220 => 26269, 27221 => 26302, 27222 => 26331, 27223 => 26332, 27224 => 26342,
     125527225 => 26345, 27226 => 36146, 27227 => 36147, 27228 => 36150, 27229 => 36155,
     125627230 => 36157, 27231 => 36160, 27232 => 36165, 27233 => 36166, 27234 => 36168,
     125727235 => 36169, 27236 => 36167, 27237 => 36173, 27238 => 36181, 27239 => 36185,
     125827240 => 35271, 27241 => 35274, 27242 => 35275, 27243 => 35276, 27244 => 35278,
     125927245 => 35279, 27246 => 35280, 27247 => 35281, 27248 => 29294, 27249 => 29343,
     126027250 => 29277, 27251 => 29286, 27252 => 29295, 27253 => 29310, 27254 => 29311,
     126127255 => 29316, 27256 => 29323, 27257 => 29325, 27258 => 29327, 27259 => 29330,
     126227260 => 25352, 27261 => 25394, 27262 => 25520, 27425 => 25663, 27426 => 25816,
     126327427 => 32772, 27428 => 27626, 27429 => 27635, 27430 => 27645, 27431 => 27637,
     126427432 => 27641, 27433 => 27653, 27434 => 27655, 27435 => 27654, 27436 => 27661,
     126527437 => 27669, 27438 => 27672, 27439 => 27673, 27440 => 27674, 27441 => 27681,
     126627442 => 27689, 27443 => 27684, 27444 => 27690, 27445 => 27698, 27446 => 25909,
     126727447 => 25941, 27448 => 25963, 27449 => 29261, 27450 => 29266, 27451 => 29270,
     126827452 => 29232, 27453 => 34402, 27454 => 21014, 27455 => 32927, 27456 => 32924,
     126927457 => 32915, 27458 => 32956, 27459 => 26378, 27460 => 32957, 27461 => 32945,
     127027462 => 32939, 27463 => 32941, 27464 => 32948, 27465 => 32951, 27466 => 32999,
     127127467 => 33000, 27468 => 33001, 27469 => 33002, 27470 => 32987, 27471 => 32962,
     127227472 => 32964, 27473 => 32985, 27474 => 32973, 27475 => 32983, 27476 => 26384,
     127327477 => 32989, 27478 => 33003, 27479 => 33009, 27480 => 33012, 27481 => 33005,
     127427482 => 33037, 27483 => 33038, 27484 => 33010, 27485 => 33020, 27486 => 26389,
     127527487 => 33042, 27488 => 35930, 27489 => 33078, 27490 => 33054, 27491 => 33068,
     127627492 => 33048, 27493 => 33074, 27494 => 33096, 27495 => 33100, 27496 => 33107,
     127727497 => 33140, 27498 => 33113, 27499 => 33114, 27500 => 33137, 27501 => 33120,
     127827502 => 33129, 27503 => 33148, 27504 => 33149, 27505 => 33133, 27506 => 33127,
     127927507 => 22605, 27508 => 23221, 27509 => 33160, 27510 => 33154, 27511 => 33169,
     128027512 => 28373, 27513 => 33187, 27514 => 33194, 27515 => 33228, 27516 => 26406,
     128127517 => 33226, 27518 => 33211, 27681 => 33217, 27682 => 33190, 27683 => 27428,
     128227684 => 27447, 27685 => 27449, 27686 => 27459, 27687 => 27462, 27688 => 27481,
     128327689 => 39121, 27690 => 39122, 27691 => 39123, 27692 => 39125, 27693 => 39129,
     128427694 => 39130, 27695 => 27571, 27696 => 24384, 27697 => 27586, 27698 => 35315,
     128527699 => 26000, 27700 => 40785, 27701 => 26003, 27702 => 26044, 27703 => 26054,
     128627704 => 26052, 27705 => 26051, 27706 => 26060, 27707 => 26062, 27708 => 26066,
     128727709 => 26070, 27710 => 28800, 27711 => 28828, 27712 => 28822, 27713 => 28829,
     128827714 => 28859, 27715 => 28864, 27716 => 28855, 27717 => 28843, 27718 => 28849,
     128927719 => 28904, 27720 => 28874, 27721 => 28944, 27722 => 28947, 27723 => 28950,
     129027724 => 28975, 27725 => 28977, 27726 => 29043, 27727 => 29020, 27728 => 29032,
     129127729 => 28997, 27730 => 29042, 27731 => 29002, 27732 => 29048, 27733 => 29050,
     129227734 => 29080, 27735 => 29107, 27736 => 29109, 27737 => 29096, 27738 => 29088,
     129327739 => 29152, 27740 => 29140, 27741 => 29159, 27742 => 29177, 27743 => 29213,
     129427744 => 29224, 27745 => 28780, 27746 => 28952, 27747 => 29030, 27748 => 29113,
     129527749 => 25150, 27750 => 25149, 27751 => 25155, 27752 => 25160, 27753 => 25161,
     129627754 => 31035, 27755 => 31040, 27756 => 31046, 27757 => 31049, 27758 => 31067,
     129727759 => 31068, 27760 => 31059, 27761 => 31066, 27762 => 31074, 27763 => 31063,
     129827764 => 31072, 27765 => 31087, 27766 => 31079, 27767 => 31098, 27768 => 31109,
     129927769 => 31114, 27770 => 31130, 27771 => 31143, 27772 => 31155, 27773 => 24529,
     130027774 => 24528, 27937 => 24636, 27938 => 24669, 27939 => 24666, 27940 => 24679,
     130127941 => 24641, 27942 => 24665, 27943 => 24675, 27944 => 24747, 27945 => 24838,
     130227946 => 24845, 27947 => 24925, 27948 => 25001, 27949 => 24989, 27950 => 25035,
     130327951 => 25041, 27952 => 25094, 27953 => 32896, 27954 => 32895, 27955 => 27795,
     130427956 => 27894, 27957 => 28156, 27958 => 30710, 27959 => 30712, 27960 => 30720,
     130527961 => 30729, 27962 => 30743, 27963 => 30744, 27964 => 30737, 27965 => 26027,
     130627966 => 30765, 27967 => 30748, 27968 => 30749, 27969 => 30777, 27970 => 30778,
     130727971 => 30779, 27972 => 30751, 27973 => 30780, 27974 => 30757, 27975 => 30764,
     130827976 => 30755, 27977 => 30761, 27978 => 30798, 27979 => 30829, 27980 => 30806,
     130927981 => 30807, 27982 => 30758, 27983 => 30800, 27984 => 30791, 27985 => 30796,
     131027986 => 30826, 27987 => 30875, 27988 => 30867, 27989 => 30874, 27990 => 30855,
     131127991 => 30876, 27992 => 30881, 27993 => 30883, 27994 => 30898, 27995 => 30905,
     131227996 => 30885, 27997 => 30932, 27998 => 30937, 27999 => 30921, 28000 => 30956,
     131328001 => 30962, 28002 => 30981, 28003 => 30964, 28004 => 30995, 28005 => 31012,
     131428006 => 31006, 28007 => 31028, 28008 => 40859, 28009 => 40697, 28010 => 40699,
     131528011 => 40700, 28012 => 30449, 28013 => 30468, 28014 => 30477, 28015 => 30457,
     131628016 => 30471, 28017 => 30472, 28018 => 30490, 28019 => 30498, 28020 => 30489,
     131728021 => 30509, 28022 => 30502, 28023 => 30517, 28024 => 30520, 28025 => 30544,
     131828026 => 30545, 28027 => 30535, 28028 => 30531, 28029 => 30554, 28030 => 30568,
     131928193 => 30562, 28194 => 30565, 28195 => 30591, 28196 => 30605, 28197 => 30589,
     132028198 => 30592, 28199 => 30604, 28200 => 30609, 28201 => 30623, 28202 => 30624,
     132128203 => 30640, 28204 => 30645, 28205 => 30653, 28206 => 30010, 28207 => 30016,
     132228208 => 30030, 28209 => 30027, 28210 => 30024, 28211 => 30043, 28212 => 30066,
     132328213 => 30073, 28214 => 30083, 28215 => 32600, 28216 => 32609, 28217 => 32607,
     132428218 => 35400, 28219 => 32616, 28220 => 32628, 28221 => 32625, 28222 => 32633,
     132528223 => 32641, 28224 => 32638, 28225 => 30413, 28226 => 30437, 28227 => 34866,
     132628228 => 38021, 28229 => 38022, 28230 => 38023, 28231 => 38027, 28232 => 38026,
     132728233 => 38028, 28234 => 38029, 28235 => 38031, 28236 => 38032, 28237 => 38036,
     132828238 => 38039, 28239 => 38037, 28240 => 38042, 28241 => 38043, 28242 => 38044,
     132928243 => 38051, 28244 => 38052, 28245 => 38059, 28246 => 38058, 28247 => 38061,
     133028248 => 38060, 28249 => 38063, 28250 => 38064, 28251 => 38066, 28252 => 38068,
     133128253 => 38070, 28254 => 38071, 28255 => 38072, 28256 => 38073, 28257 => 38074,
     133228258 => 38076, 28259 => 38077, 28260 => 38079, 28261 => 38084, 28262 => 38088,
     133328263 => 38089, 28264 => 38090, 28265 => 38091, 28266 => 38092, 28267 => 38093,
     133428268 => 38094, 28269 => 38096, 28270 => 38097, 28271 => 38098, 28272 => 38101,
     133528273 => 38102, 28274 => 38103, 28275 => 38105, 28276 => 38104, 28277 => 38107,
     133628278 => 38110, 28279 => 38111, 28280 => 38112, 28281 => 38114, 28282 => 38116,
     133728283 => 38117, 28284 => 38119, 28285 => 38120, 28286 => 38122, 28449 => 38121,
     133828450 => 38123, 28451 => 38126, 28452 => 38127, 28453 => 38131, 28454 => 38132,
     133928455 => 38133, 28456 => 38135, 28457 => 38137, 28458 => 38140, 28459 => 38141,
     134028460 => 38143, 28461 => 38147, 28462 => 38146, 28463 => 38150, 28464 => 38151,
     134128465 => 38153, 28466 => 38154, 28467 => 38157, 28468 => 38158, 28469 => 38159,
     134228470 => 38162, 28471 => 38163, 28472 => 38164, 28473 => 38165, 28474 => 38166,
     134328475 => 38168, 28476 => 38171, 28477 => 38173, 28478 => 38174, 28479 => 38175,
     134428480 => 38178, 28481 => 38186, 28482 => 38187, 28483 => 38185, 28484 => 38188,
     134528485 => 38193, 28486 => 38194, 28487 => 38196, 28488 => 38198, 28489 => 38199,
     134628490 => 38200, 28491 => 38204, 28492 => 38206, 28493 => 38207, 28494 => 38210,
     134728495 => 38197, 28496 => 38212, 28497 => 38213, 28498 => 38214, 28499 => 38217,
     134828500 => 38220, 28501 => 38222, 28502 => 38223, 28503 => 38226, 28504 => 38227,
     134928505 => 38228, 28506 => 38230, 28507 => 38231, 28508 => 38232, 28509 => 38233,
     135028510 => 38235, 28511 => 38238, 28512 => 38239, 28513 => 38237, 28514 => 38241,
     135128515 => 38242, 28516 => 38244, 28517 => 38245, 28518 => 38246, 28519 => 38247,
     135228520 => 38248, 28521 => 38249, 28522 => 38250, 28523 => 38251, 28524 => 38252,
     135328525 => 38255, 28526 => 38257, 28527 => 38258, 28528 => 38259, 28529 => 38202,
     135428530 => 30695, 28531 => 30700, 28532 => 38601, 28533 => 31189, 28534 => 31213,
     135528535 => 31203, 28536 => 31211, 28537 => 31238, 28538 => 23879, 28539 => 31235,
     135628540 => 31234, 28541 => 31262, 28542 => 31252, 28705 => 31289, 28706 => 31287,
     135728707 => 31313, 28708 => 40655, 28709 => 39333, 28710 => 31344, 28711 => 30344,
     135828712 => 30350, 28713 => 30355, 28714 => 30361, 28715 => 30372, 28716 => 29918,
     135928717 => 29920, 28718 => 29996, 28719 => 40480, 28720 => 40482, 28721 => 40488,
     136028722 => 40489, 28723 => 40490, 28724 => 40491, 28725 => 40492, 28726 => 40498,
     136128727 => 40497, 28728 => 40502, 28729 => 40504, 28730 => 40503, 28731 => 40505,
     136228732 => 40506, 28733 => 40510, 28734 => 40513, 28735 => 40514, 28736 => 40516,
     136328737 => 40518, 28738 => 40519, 28739 => 40520, 28740 => 40521, 28741 => 40523,
     136428742 => 40524, 28743 => 40526, 28744 => 40529, 28745 => 40533, 28746 => 40535,
     136528747 => 40538, 28748 => 40539, 28749 => 40540, 28750 => 40542, 28751 => 40547,
     136628752 => 40550, 28753 => 40551, 28754 => 40552, 28755 => 40553, 28756 => 40554,
     136728757 => 40555, 28758 => 40556, 28759 => 40561, 28760 => 40557, 28761 => 40563,
     136828762 => 30098, 28763 => 30100, 28764 => 30102, 28765 => 30112, 28766 => 30109,
     136928767 => 30124, 28768 => 30115, 28769 => 30131, 28770 => 30132, 28771 => 30136,
     137028772 => 30148, 28773 => 30129, 28774 => 30128, 28775 => 30147, 28776 => 30146,
     137128777 => 30166, 28778 => 30157, 28779 => 30179, 28780 => 30184, 28781 => 30182,
     137228782 => 30180, 28783 => 30187, 28784 => 30183, 28785 => 30211, 28786 => 30193,
     137328787 => 30204, 28788 => 30207, 28789 => 30224, 28790 => 30208, 28791 => 30213,
     137428792 => 30220, 28793 => 30231, 28794 => 30218, 28795 => 30245, 28796 => 30232,
     137528797 => 30229, 28798 => 30233, 28961 => 30235, 28962 => 30268, 28963 => 30242,
     137628964 => 30240, 28965 => 30272, 28966 => 30253, 28967 => 30256, 28968 => 30271,
     137728969 => 30261, 28970 => 30275, 28971 => 30270, 28972 => 30259, 28973 => 30285,
     137828974 => 30302, 28975 => 30292, 28976 => 30300, 28977 => 30294, 28978 => 30315,
     137928979 => 30319, 28980 => 32714, 28981 => 31462, 28982 => 31352, 28983 => 31353,
     138028984 => 31360, 28985 => 31366, 28986 => 31368, 28987 => 31381, 28988 => 31398,
     138128989 => 31392, 28990 => 31404, 28991 => 31400, 28992 => 31405, 28993 => 31411,
     138228994 => 34916, 28995 => 34921, 28996 => 34930, 28997 => 34941, 28998 => 34943,
     138328999 => 34946, 29000 => 34978, 29001 => 35014, 29002 => 34999, 29003 => 35004,
     138429004 => 35017, 29005 => 35042, 29006 => 35022, 29007 => 35043, 29008 => 35045,
     138529009 => 35057, 29010 => 35098, 29011 => 35068, 29012 => 35048, 29013 => 35070,
     138629014 => 35056, 29015 => 35105, 29016 => 35097, 29017 => 35091, 29018 => 35099,
     138729019 => 35082, 29020 => 35124, 29021 => 35115, 29022 => 35126, 29023 => 35137,
     138829024 => 35174, 29025 => 35195, 29026 => 30091, 29027 => 32997, 29028 => 30386,
     138929029 => 30388, 29030 => 30684, 29031 => 32786, 29032 => 32788, 29033 => 32790,
     139029034 => 32796, 29035 => 32800, 29036 => 32802, 29037 => 32805, 29038 => 32806,
     139129039 => 32807, 29040 => 32809, 29041 => 32808, 29042 => 32817, 29043 => 32779,
     139229044 => 32821, 29045 => 32835, 29046 => 32838, 29047 => 32845, 29048 => 32850,
     139329049 => 32873, 29050 => 32881, 29051 => 35203, 29052 => 39032, 29053 => 39040,
     139429054 => 39043, 29217 => 39049, 29218 => 39052, 29219 => 39053, 29220 => 39055,
     139529221 => 39060, 29222 => 39066, 29223 => 39067, 29224 => 39070, 29225 => 39071,
     139629226 => 39073, 29227 => 39074, 29228 => 39077, 29229 => 39078, 29230 => 34381,
     139729231 => 34388, 29232 => 34412, 29233 => 34414, 29234 => 34431, 29235 => 34426,
     139829236 => 34428, 29237 => 34427, 29238 => 34472, 29239 => 34445, 29240 => 34443,
     139929241 => 34476, 29242 => 34461, 29243 => 34471, 29244 => 34467, 29245 => 34474,
     140029246 => 34451, 29247 => 34473, 29248 => 34486, 29249 => 34500, 29250 => 34485,
     140129251 => 34510, 29252 => 34480, 29253 => 34490, 29254 => 34481, 29255 => 34479,
     140229256 => 34505, 29257 => 34511, 29258 => 34484, 29259 => 34537, 29260 => 34545,
     140329261 => 34546, 29262 => 34541, 29263 => 34547, 29264 => 34512, 29265 => 34579,
     140429266 => 34526, 29267 => 34548, 29268 => 34527, 29269 => 34520, 29270 => 34513,
     140529271 => 34563, 29272 => 34567, 29273 => 34552, 29274 => 34568, 29275 => 34570,
     140629276 => 34573, 29277 => 34569, 29278 => 34595, 29279 => 34619, 29280 => 34590,
     140729281 => 34597, 29282 => 34606, 29283 => 34586, 29284 => 34622, 29285 => 34632,
     140829286 => 34612, 29287 => 34609, 29288 => 34601, 29289 => 34615, 29290 => 34623,
     140929291 => 34690, 29292 => 34594, 29293 => 34685, 29294 => 34686, 29295 => 34683,
     141029296 => 34656, 29297 => 34672, 29298 => 34636, 29299 => 34670, 29300 => 34699,
     141129301 => 34643, 29302 => 34659, 29303 => 34684, 29304 => 34660, 29305 => 34649,
     141229306 => 34661, 29307 => 34707, 29308 => 34735, 29309 => 34728, 29310 => 34770,
     141329473 => 34758, 29474 => 34696, 29475 => 34693, 29476 => 34733, 29477 => 34711,
     141429478 => 34691, 29479 => 34731, 29480 => 34789, 29481 => 34732, 29482 => 34741,
     141529483 => 34739, 29484 => 34763, 29485 => 34771, 29486 => 34749, 29487 => 34769,
     141629488 => 34752, 29489 => 34762, 29490 => 34779, 29491 => 34794, 29492 => 34784,
     141729493 => 34798, 29494 => 34838, 29495 => 34835, 29496 => 34814, 29497 => 34826,
     141829498 => 34843, 29499 => 34849, 29500 => 34873, 29501 => 34876, 29502 => 32566,
     141929503 => 32578, 29504 => 32580, 29505 => 32581, 29506 => 33296, 29507 => 31482,
     142029508 => 31485, 29509 => 31496, 29510 => 31491, 29511 => 31492, 29512 => 31509,
     142129513 => 31498, 29514 => 31531, 29515 => 31503, 29516 => 31559, 29517 => 31544,
     142229518 => 31530, 29519 => 31513, 29520 => 31534, 29521 => 31537, 29522 => 31520,
     142329523 => 31525, 29524 => 31524, 29525 => 31539, 29526 => 31550, 29527 => 31518,
     142429528 => 31576, 29529 => 31578, 29530 => 31557, 29531 => 31605, 29532 => 31564,
     142529533 => 31581, 29534 => 31584, 29535 => 31598, 29536 => 31611, 29537 => 31586,
     142629538 => 31602, 29539 => 31601, 29540 => 31632, 29541 => 31654, 29542 => 31655,
     142729543 => 31672, 29544 => 31660, 29545 => 31645, 29546 => 31656, 29547 => 31621,
     142829548 => 31658, 29549 => 31644, 29550 => 31650, 29551 => 31659, 29552 => 31668,
     142929553 => 31697, 29554 => 31681, 29555 => 31692, 29556 => 31709, 29557 => 31706,
     143029558 => 31717, 29559 => 31718, 29560 => 31722, 29561 => 31756, 29562 => 31742,
     143129563 => 31740, 29564 => 31759, 29565 => 31766, 29566 => 31755, 29729 => 31775,
     143229730 => 31786, 29731 => 31782, 29732 => 31800, 29733 => 31809, 29734 => 31808,
     143329735 => 33278, 29736 => 33281, 29737 => 33282, 29738 => 33284, 29739 => 33260,
     143429740 => 34884, 29741 => 33313, 29742 => 33314, 29743 => 33315, 29744 => 33325,
     143529745 => 33327, 29746 => 33320, 29747 => 33323, 29748 => 33336, 29749 => 33339,
     143629750 => 33331, 29751 => 33332, 29752 => 33342, 29753 => 33348, 29754 => 33353,
     143729755 => 33355, 29756 => 33359, 29757 => 33370, 29758 => 33375, 29759 => 33384,
     143829760 => 34942, 29761 => 34949, 29762 => 34952, 29763 => 35032, 29764 => 35039,
     143929765 => 35166, 29766 => 32669, 29767 => 32671, 29768 => 32679, 29769 => 32687,
     144029770 => 32688, 29771 => 32690, 29772 => 31868, 29773 => 25929, 29774 => 31889,
     144129775 => 31901, 29776 => 31900, 29777 => 31902, 29778 => 31906, 29779 => 31922,
     144229780 => 31932, 29781 => 31933, 29782 => 31937, 29783 => 31943, 29784 => 31948,
     144329785 => 31949, 29786 => 31944, 29787 => 31941, 29788 => 31959, 29789 => 31976,
     144429790 => 33390, 29791 => 26280, 29792 => 32703, 29793 => 32718, 29794 => 32725,
     144529795 => 32741, 29796 => 32737, 29797 => 32742, 29798 => 32745, 29799 => 32750,
     144629800 => 32755, 29801 => 31992, 29802 => 32119, 29803 => 32166, 29804 => 32174,
     144729805 => 32327, 29806 => 32411, 29807 => 40632, 29808 => 40628, 29809 => 36211,
     144829810 => 36228, 29811 => 36244, 29812 => 36241, 29813 => 36273, 29814 => 36199,
     144929815 => 36205, 29816 => 35911, 29817 => 35913, 29818 => 37194, 29819 => 37200,
     145029820 => 37198, 29821 => 37199, 29822 => 37220, 29985 => 37218, 29986 => 37217,
     145129987 => 37232, 29988 => 37225, 29989 => 37231, 29990 => 37245, 29991 => 37246,
     145229992 => 37234, 29993 => 37236, 29994 => 37241, 29995 => 37260, 29996 => 37253,
     145329997 => 37264, 29998 => 37261, 29999 => 37265, 30000 => 37282, 30001 => 37283,
     145430002 => 37290, 30003 => 37293, 30004 => 37294, 30005 => 37295, 30006 => 37301,
     145530007 => 37300, 30008 => 37306, 30009 => 35925, 30010 => 40574, 30011 => 36280,
     145630012 => 36331, 30013 => 36357, 30014 => 36441, 30015 => 36457, 30016 => 36277,
     145730017 => 36287, 30018 => 36284, 30019 => 36282, 30020 => 36292, 30021 => 36310,
     145830022 => 36311, 30023 => 36314, 30024 => 36318, 30025 => 36302, 30026 => 36303,
     145930027 => 36315, 30028 => 36294, 30029 => 36332, 30030 => 36343, 30031 => 36344,
     146030032 => 36323, 30033 => 36345, 30034 => 36347, 30035 => 36324, 30036 => 36361,
     146130037 => 36349, 30038 => 36372, 30039 => 36381, 30040 => 36383, 30041 => 36396,
     146230042 => 36398, 30043 => 36387, 30044 => 36399, 30045 => 36410, 30046 => 36416,
     146330047 => 36409, 30048 => 36405, 30049 => 36413, 30050 => 36401, 30051 => 36425,
     146430052 => 36417, 30053 => 36418, 30054 => 36433, 30055 => 36434, 30056 => 36426,
     146530057 => 36464, 30058 => 36470, 30059 => 36476, 30060 => 36463, 30061 => 36468,
     146630062 => 36485, 30063 => 36495, 30064 => 36500, 30065 => 36496, 30066 => 36508,
     146730067 => 36510, 30068 => 35960, 30069 => 35970, 30070 => 35978, 30071 => 35973,
     146830072 => 35992, 30073 => 35988, 30074 => 26011, 30075 => 35286, 30076 => 35294,
     146930077 => 35290, 30078 => 35292, 30241 => 35301, 30242 => 35307, 30243 => 35311,
     147030244 => 35390, 30245 => 35622, 30246 => 38739, 30247 => 38633, 30248 => 38643,
     147130249 => 38639, 30250 => 38662, 30251 => 38657, 30252 => 38664, 30253 => 38671,
     147230254 => 38670, 30255 => 38698, 30256 => 38701, 30257 => 38704, 30258 => 38718,
     147330259 => 40832, 30260 => 40835, 30261 => 40837, 30262 => 40838, 30263 => 40839,
     147430264 => 40840, 30265 => 40841, 30266 => 40842, 30267 => 40844, 30268 => 40702,
     147530269 => 40715, 30270 => 40717, 30271 => 38585, 30272 => 38588, 30273 => 38589,
     147630274 => 38606, 30275 => 38610, 30276 => 30655, 30277 => 38624, 30278 => 37518,
     147730279 => 37550, 30280 => 37576, 30281 => 37694, 30282 => 37738, 30283 => 37834,
     147830284 => 37775, 30285 => 37950, 30286 => 37995, 30287 => 40063, 30288 => 40066,
     147930289 => 40069, 30290 => 40070, 30291 => 40071, 30292 => 40072, 30293 => 31267,
     148030294 => 40075, 30295 => 40078, 30296 => 40080, 30297 => 40081, 30298 => 40082,
     148130299 => 40084, 30300 => 40085, 30301 => 40090, 30302 => 40091, 30303 => 40094,
     148230304 => 40095, 30305 => 40096, 30306 => 40097, 30307 => 40098, 30308 => 40099,
     148330309 => 40101, 30310 => 40102, 30311 => 40103, 30312 => 40104, 30313 => 40105,
     148430314 => 40107, 30315 => 40109, 30316 => 40110, 30317 => 40112, 30318 => 40113,
     148530319 => 40114, 30320 => 40115, 30321 => 40116, 30322 => 40117, 30323 => 40118,
     148630324 => 40119, 30325 => 40122, 30326 => 40123, 30327 => 40124, 30328 => 40125,
     148730329 => 40132, 30330 => 40133, 30331 => 40134, 30332 => 40135, 30333 => 40138,
     148830334 => 40139, 30497 => 40140, 30498 => 40141, 30499 => 40142, 30500 => 40143,
     148930501 => 40144, 30502 => 40147, 30503 => 40148, 30504 => 40149, 30505 => 40151,
     149030506 => 40152, 30507 => 40153, 30508 => 40156, 30509 => 40157, 30510 => 40159,
     149130511 => 40162, 30512 => 38780, 30513 => 38789, 30514 => 38801, 30515 => 38802,
     149230516 => 38804, 30517 => 38831, 30518 => 38827, 30519 => 38819, 30520 => 38834,
     149330521 => 38836, 30522 => 39601, 30523 => 39600, 30524 => 39607, 30525 => 40536,
     149430526 => 39606, 30527 => 39610, 30528 => 39612, 30529 => 39617, 30530 => 39616,
     149530531 => 39621, 30532 => 39618, 30533 => 39627, 30534 => 39628, 30535 => 39633,
     149630536 => 39749, 30537 => 39747, 30538 => 39751, 30539 => 39753, 30540 => 39752,
     149730541 => 39757, 30542 => 39761, 30543 => 39144, 30544 => 39181, 30545 => 39214,
     149830546 => 39253, 30547 => 39252, 30548 => 39647, 30549 => 39649, 30550 => 39654,
     149930551 => 39663, 30552 => 39659, 30553 => 39675, 30554 => 39661, 30555 => 39673,
     150030556 => 39688, 30557 => 39695, 30558 => 39699, 30559 => 39711, 30560 => 39715,
     150130561 => 40637, 30562 => 40638, 30563 => 32315, 30564 => 40578, 30565 => 40583,
     150230566 => 40584, 30567 => 40587, 30568 => 40594, 30569 => 37846, 30570 => 40605,
     150330571 => 40607, 30572 => 40667, 30573 => 40668, 30574 => 40669, 30575 => 40672,
     150430576 => 40671, 30577 => 40674, 30578 => 40681, 30579 => 40679, 30580 => 40677,
     150530581 => 40682, 30582 => 40687, 30583 => 40738, 30584 => 40748, 30585 => 40751,
     150630586 => 40761, 30587 => 40759, 30588 => 40765, 30589 => 40766, 30590 => 40772,
     15070 => 0 );
    15081508
    15091509    function gb2utf8($gb) {
    1510         if( !trim($gb) ) return $gb;
    1511         $utf8='';
    1512         while($gb) {
    1513             if( ord(substr($gb,0,1)) > 127 ) {
    1514                 $t=substr($gb,0,2);
    1515                 $gb=substr($gb,2);
    1516                 $utf8 .= $this->u2utf8($this->codetable[hexdec(bin2hex($t))-0x8080]);
    1517             }
    1518             else {
    1519                 $t=substr($gb,0,1);
    1520                 $gb=substr($gb,1);
    1521                 $utf8 .= $this->u2utf8($t);
    1522             }
    1523         }
    1524         return $utf8;
     1510        if( !trim($gb) ) return $gb;
     1511        $utf8='';
     1512        while($gb) {
     1513            if( ord(substr($gb,0,1)) > 127 ) {
     1514                $t=substr($gb,0,2);
     1515                $gb=substr($gb,2);
     1516                $utf8 .= $this->u2utf8($this->codetable[hexdec(bin2hex($t))-0x8080]);
     1517            }
     1518            else {
     1519                $t=substr($gb,0,1);
     1520                $gb=substr($gb,1);
     1521                $utf8 .= $this->u2utf8($t);
     1522            }
     1523        }
     1524        return $utf8;
     1525    }
     1526   
     1527    function u2utf8($c) {
     1528        $str='';
     1529        if ($c < 0x80) {
     1530            $str.=$c;
     1531            }
     1532        else if ($c < 0x800) {
     1533            $str.=chr(0xC0 | $c>>6);
     1534            $str.=chr(0x80 | $c & 0x3F);
     1535            }
     1536        else if ($c < 0x10000) {
     1537            $str.=chr(0xE0 | $c>>12);
     1538            $str.=chr(0x80 | $c>>6 & 0x3F);
     1539                $str.=chr(0x80 | $c & 0x3F);
     1540        }
     1541        else if ($c < 0x200000) {
     1542            $str.=chr(0xF0 | $c>>18);
     1543            $str.=chr(0x80 | $c>>12 & 0x3F);
     1544            $str.=chr(0x80 | $c>>6 & 0x3F);
     1545            $str.=chr(0x80 | $c & 0x3F);
     1546        }
     1547        return $str;
    15251548    }
    15261549
    1527     function u2utf8($c) {
    1528         $str='';
    1529         if ($c < 0x80) {
    1530             $str.=$c;
    1531         }
    1532         else if ($c < 0x800) {
    1533             $str.=chr(0xC0 | $c>>6);
    1534             $str.=chr(0x80 | $c & 0x3F);
    1535         }
    1536         else if ($c < 0x10000) {
    1537             $str.=chr(0xE0 | $c>>12);
    1538             $str.=chr(0x80 | $c>>6 & 0x3F);
    1539             $str.=chr(0x80 | $c & 0x3F);
    1540         }
    1541         else if ($c < 0x200000) {
    1542             $str.=chr(0xF0 | $c>>18);
    1543             $str.=chr(0x80 | $c>>12 & 0x3F);
    1544             $str.=chr(0x80 | $c>>6 & 0x3F);
    1545             $str.=chr(0x80 | $c & 0x3F);
    1546         }
    1547         return $str;
    1548     }
    1549 
    1550 } // END Class
     1550} // END Class
    15511551
    15521552?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_gradient.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_GRADIENT.PHP
    4  // Description: Create a color gradient
    5  // Created:     2003-02-01
    6  // Ver:         $Id: jpgraph_gradient.php 1761 2009-08-01 08:31:28Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_GRADIENT.PHP
     4// Description: Create a color gradient
     5// Created:     2003-02-01
     6// Ver:         $Id: jpgraph_gradient.php 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212// Styles for gradient color fill
     
    2323define("GRAD_RAISED_PANEL",10);
    2424define("GRAD_DIAGONAL",11);
    25 
     25 
    2626//===================================================
    2727// CLASS Gradient
     
    3131class Gradient {
    3232    private $img=null, $numcolors=100;
    33     //---------------
    34     // CONSTRUCTOR
    35     function __construct(&$img) {
    36         $this->img = $img;
     33//---------------
     34// CONSTRUCTOR
     35    function Gradient(&$img) {
     36        $this->img = $img;
    3737    }
    3838
    3939
    4040    function SetNumColors($aNum) {
    41         $this->numcolors=$aNum;
     41        $this->numcolors=$aNum;
    4242    }
    43     //---------------
    44     // PUBLIC METHODS
     43//---------------
     44// PUBLIC METHODS       
    4545    // Produce a gradient filled rectangle with a smooth transition between
    4646    // two colors.
    47     // ($xl,$yt)  Top left corner
    48     // ($xr,$yb) Bottom right
    49     // $from_color Starting color in gradient
    50     // $to_color End color in the gradient
    51     // $style  Which way is the gradient oriented?
     47    // ($xl,$yt)        Top left corner
     48    // ($xr,$yb)        Bottom right
     49    // $from_color      Starting color in gradient
     50    // $to_color        End color in the gradient
     51    // $style           Which way is the gradient oriented?
    5252    function FilledRectangle($xl,$yt,$xr,$yb,$from_color,$to_color,$style=1) {
    53         $this->img->SetLineWeight(1);
    54         switch( $style ) {
    55             case GRAD_VER:
    56                 $steps = ceil(abs($xr-$xl)+1);
    57                 $delta = $xr>=$xl ? 1 : -1;
    58                 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
    59                 for( $i=0, $x=$xl; $i < $steps; ++$i ) {
    60                     $this->img->current_color = $colors[$i];
    61                     $this->img->Line($x,$yt,$x,$yb);
    62                     $x += $delta;
    63                 }
    64                 break;
    65 
    66             case GRAD_HOR:
    67                 $steps = ceil(abs($yb-$yt)+1);
    68                 $delta = $yb >= $yt ? 1 : -1;
    69                 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
    70                 for($i=0,$y=$yt; $i < $steps; ++$i) {
    71                     $this->img->current_color = $colors[$i];
    72                     $this->img->Line($xl,$y,$xr,$y);
    73                     $y += $delta;
    74                 }
    75                 break;
    76 
    77             case GRAD_MIDHOR:
    78                 $steps = ceil(abs($yb-$yt)/2);
    79                 $delta = $yb >= $yt ? 1 : -1;
    80                 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
    81                 for($y=$yt, $i=0; $i < $steps;  ++$i) {
    82                     $this->img->current_color = $colors[$i];
    83                     $this->img->Line($xl,$y,$xr,$y);
    84                     $y += $delta;
    85                 }
    86                 --$i;
    87                 if( abs($yb-$yt) % 2 == 1 ) {
    88                     --$steps;
    89                 }
    90                 for($j=0; $j < $steps; ++$j, --$i) {
    91                     $this->img->current_color = $colors[$i];
    92                     $this->img->Line($xl,$y,$xr,$y);
    93                     $y += $delta;
    94                 }
    95                 $this->img->Line($xl,$y,$xr,$y);
    96                 break;
    97 
    98             case GRAD_MIDVER:
    99                 $steps = ceil(abs($xr-$xl)/2);
    100                 $delta = $xr>=$xl ? 1 : -1;
    101                 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
    102                 for($x=$xl, $i=0; $i < $steps; ++$i) {
    103                     $this->img->current_color = $colors[$i];
    104                     $this->img->Line($x,$yb,$x,$yt);
    105                     $x += $delta;
    106                 }
    107                 --$i;
    108                 if( abs($xr-$xl) % 2 == 1 ) {
    109                     --$steps;
    110                 }
    111                 for($j=0; $j < $steps; ++$j, --$i) {
    112                     $this->img->current_color = $colors[$i];
    113                     $this->img->Line($x,$yb,$x,$yt);
    114                     $x += $delta;
    115                 }
    116                 $this->img->Line($x,$yb,$x,$yt);
    117                 break;
    118 
    119             case GRAD_WIDE_MIDVER:
    120                 $diff = ceil(abs($xr-$xl));
    121                 $steps = floor(abs($diff)/3);
    122                 $firststep = $diff - 2*$steps ;
    123                 $delta = $xr >= $xl ? 1 : -1;
    124                 $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
    125                 for($x=$xl, $i=0; $i < $firststep; ++$i) {
    126                     $this->img->current_color = $colors[$i];
    127                     $this->img->Line($x,$yb,$x,$yt);
    128                     $x += $delta;
    129                 }
    130                 --$i;
    131                 $this->img->current_color = $colors[$i];
    132                 for($j=0; $j< $steps; ++$j) {
    133                     $this->img->Line($x,$yb,$x,$yt);
    134                     $x += $delta;
    135                 }
    136 
    137                 for($j=0; $j < $steps; ++$j, --$i) {
    138                     $this->img->current_color = $colors[$i];
    139                     $this->img->Line($x,$yb,$x,$yt);
    140                     $x += $delta;
    141                 }
    142                 break;
    143 
    144             case GRAD_WIDE_MIDHOR:
    145                 $diff = ceil(abs($yb-$yt));
    146                 $steps = floor(abs($diff)/3);
    147                 $firststep = $diff - 2*$steps ;
    148                 $delta = $yb >= $yt? 1 : -1;
    149                 $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
    150                 for($y=$yt, $i=0; $i < $firststep;  ++$i) {
    151                     $this->img->current_color = $colors[$i];
    152                     $this->img->Line($xl,$y,$xr,$y);
    153                     $y += $delta;
    154                 }
    155                 --$i;
    156                 $this->img->current_color = $colors[$i];
    157                 for($j=0; $j < $steps; ++$j) {
    158                     $this->img->Line($xl,$y,$xr,$y);
    159                     $y += $delta;
    160                 }
    161                 for($j=0; $j < $steps; ++$j, --$i) {
    162                     $this->img->current_color = $colors[$i];
    163                     $this->img->Line($xl,$y,$xr,$y);
    164                     $y += $delta;
    165                 }
    166                 break;
    167 
    168             case GRAD_LEFT_REFLECTION:
    169                 $steps1 = ceil(0.3*abs($xr-$xl));
    170                 $delta = $xr>=$xl ? 1 : -1;
    171 
    172                 $from_color = $this->img->rgb->Color($from_color);
    173                 $adj = 1.4;
    174                 $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2]))));
    175                 $from_color2 = array(min(255,$from_color[0]+$m),
    176                 min(255,$from_color[1]+$m), min(255,$from_color[2]+$m));
    177 
    178                 $this->GetColArray($from_color2,$to_color,$steps1,$colors,$this->numcolors);
    179                 $n = count($colors);
    180                 for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
    181                     $this->img->current_color = $colors[$i];
    182                     $this->img->Line($x,$yb,$x,$yt);
    183                     $x += $delta;
    184                 }
    185                 $steps2 = max(1,ceil(0.08*abs($xr-$xl)));
    186                 $this->img->SetColor($to_color);
    187                 for($j=0; $j< $steps2; ++$j) {
    188                     $this->img->Line($x,$yb,$x,$yt);
    189                     $x += $delta;
    190                 }
    191                 $steps = abs($xr-$xl)-$steps1-$steps2;
    192                 $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors);
    193                 $n = count($colors);
    194                 for($i=0; $i < $steps && $i < $n; ++$i) {
    195                     $this->img->current_color = $colors[$i];
    196                     $this->img->Line($x,$yb,$x,$yt);
    197                     $x += $delta;
    198                 }
    199                 break;
    200 
    201             case GRAD_RIGHT_REFLECTION:
    202                 $steps1 = ceil(0.7*abs($xr-$xl));
    203                 $delta = $xr>=$xl ? 1 : -1;
    204 
    205                 $this->GetColArray($from_color,$to_color,$steps1,$colors,$this->numcolors);
    206                 $n = count($colors);
    207                 for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
    208                     $this->img->current_color = $colors[$i];
    209                     $this->img->Line($x,$yb,$x,$yt);
    210                     $x += $delta;
    211                 }
    212                 $steps2 = max(1,ceil(0.08*abs($xr-$xl)));
    213                 $this->img->SetColor($to_color);
    214                 for($j=0; $j< $steps2; ++$j) {
    215                     $this->img->Line($x,$yb,$x,$yt);
    216                     $x += $delta;
    217                 }
    218 
    219                 $from_color = $this->img->rgb->Color($from_color);
    220                 $adj = 1.4;
    221                 $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2]))));
    222                 $from_color = array(min(255,$from_color[0]+$m),
    223                 min(255,$from_color[1]+$m), min(255,$from_color[2]+$m));
    224 
    225                 $steps = abs($xr-$xl)-$steps1-$steps2;
    226                 $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors);
    227                 $n = count($colors);
    228                 for($i=0; $i < $steps && $i < $n; ++$i) {
    229                     $this->img->current_color = $colors[$i];
    230                     $this->img->Line($x,$yb,$x,$yt);
    231                     $x += $delta;
    232                 }
    233                 break;
    234 
    235             case GRAD_CENTER:
    236                 $steps = ceil(min(($yb-$yt)+1,($xr-$xl)+1)/2);
    237                 $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
    238                 $dx = ($xr-$xl)/2;
    239                 $dy = ($yb-$yt)/2;
    240                 $x=$xl;$y=$yt;$x2=$xr;$y2=$yb;
    241                 $n = count($colors);
    242                 for($x=$xl, $i=0; $x < $xl+$dx && $y < $yt+$dy && $i < $n; ++$x, ++$y, --$x2, --$y2, ++$i) {
    243                     $this->img->current_color = $colors[$i];
    244                     $this->img->Rectangle($x,$y,$x2,$y2);
    245                 }
    246                 $this->img->Line($x,$y,$x2,$y2);
    247                 break;
    248 
    249             case GRAD_RAISED_PANEL:
    250                 // right to left
    251                 $steps1 = $xr-$xl;
    252                 $delta = $xr>=$xl ? 1 : -1;
    253                 $this->GetColArray($to_color,$from_color,$steps1,$colors,$this->numcolors);
    254                 $n = count($colors);
    255                 for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
    256                     $this->img->current_color = $colors[$i];
    257                     $this->img->Line($x,$yb,$x,$yt);
    258                     $x += $delta;
    259                 }
    260 
    261                 // left to right
    262                 $xr -= 3;
    263                 $xl += 3;
    264                 $yb -= 3;
    265                 $yt += 3;
    266                 $steps2 = $xr-$xl;
    267                 $delta = $xr>=$xl ? 1 : -1;
    268                 for($x=$xl, $j=$steps2; $j >= 0; --$j) {
    269                     $this->img->current_color = $colors[$j];
    270                     $this->img->Line($x,$yb,$x,$yt);
    271                     $x += $delta;
    272                 }
    273                 break;
    274 
    275             case GRAD_DIAGONAL:
    276                 // use the longer dimension to determine the required number of steps.
    277                 // first loop draws from one corner to the mid-diagonal and the second
    278                 // loop draws from the mid-diagonal to the opposing corner.
    279                 if($xr-$xl > $yb - $yt) {
    280                     // width is greater than height -> use x-dimension for steps
    281                     $steps = $xr-$xl;
    282                     $delta = $xr>=$xl ? 1 : -1;
    283                     $this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors);
    284                     $n = count($colors);
    285 
    286                     for($x=$xl, $i=0; $i < $steps && $i < $n; ++$i) {
    287                         $this->img->current_color = $colors[$i];
    288                         $y = $yt+($i/$steps)*($yb-$yt)*$delta;
    289                         $this->img->Line($x,$yt,$xl,$y);
    290                         $x += $delta;
    291                     }
    292 
    293                     for($x=$xl, $i = 0; $i < $steps && $i < $n; ++$i) {
    294                         $this->img->current_color = $colors[$steps+$i];
    295                         $y = $yt+($i/$steps)*($yb-$yt)*$delta;
    296                         $this->img->Line($x,$yb,$xr,$y);
    297                         $x += $delta;
    298                     }
    299                 } else {
    300                     // height is greater than width -> use y-dimension for steps
    301                     $steps = $yb-$yt;
    302                     $delta = $yb>=$yt ? 1 : -1;
    303                     $this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors);
    304                     $n = count($colors);
    305 
    306                     for($y=$yt, $i=0; $i < $steps && $i < $n; ++$i) {
    307                         $this->img->current_color = $colors[$i];
    308                         $x = $xl+($i/$steps)*($xr-$xl)*$delta;
    309                         $this->img->Line($x,$yt,$xl,$y);
    310                         $y += $delta;
    311                     }
    312 
    313                     for($y=$yt, $i = 0; $i < $steps && $i < $n; ++$i) {
    314                         $this->img->current_color = $colors[$steps+$i];
    315                         $x = $xl+($i/$steps)*($xr-$xl)*$delta;
    316                         $this->img->Line($x,$yb,$xr,$y);
    317                         $x += $delta;
    318                     }
    319 
    320                 }
    321                 break;
    322 
    323             default:
    324                 JpGraphError::RaiseL(7001,$style);
    325                 //("Unknown gradient style (=$style).");
    326                 break;
    327         }
     53        switch( $style ) {     
     54            case GRAD_VER: 
     55                $steps = ceil(abs($xr-$xl));
     56                $delta = $xr>=$xl ? 1 : -1;
     57                $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
     58                for( $i=0, $x=$xl; $i < $steps; ++$i ) {
     59                    $this->img->current_color = $colors[$i];
     60                    $this->img->Line($x,$yt,$x,$yb);
     61                    $x += $delta;
     62                }
     63                break;
     64
     65            case GRAD_HOR:
     66                $steps = ceil(abs($yb-$yt));
     67                $delta = $yb>=$yt ? 1 : -1;
     68                $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
     69                for($i=0,$y=$yt; $i < $steps; ++$i) {
     70                    $this->img->current_color = $colors[$i];
     71                    $this->img->Line($xl,$y,$xr,$y);
     72                    $y += $delta;
     73                }
     74                break;
     75
     76            case GRAD_MIDHOR:
     77                $steps = ceil(abs($yb-$yt)/2);
     78                $delta = $yb >= $yt ? 1 : -1;
     79                $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
     80                for($y=$yt, $i=0; $i < $steps;  ++$i) {
     81                    $this->img->current_color = $colors[$i];
     82                    $this->img->Line($xl,$y,$xr,$y);
     83                    $y += $delta;
     84                }
     85                --$i;
     86                if( abs($yb-$yt) % 2 == 1 ) --$steps;
     87                for($j=0; $j < $steps; ++$j, --$i) {
     88                    $this->img->current_color = $colors[$i];
     89                    $this->img->Line($xl,$y,$xr,$y);
     90                    $y += $delta;
     91                }
     92                $this->img->Line($xl,$y,$xr,$y);
     93                break;
     94
     95            case GRAD_MIDVER:
     96                $steps = ceil(abs($xr-$xl)/2);
     97                $delta = $xr>=$xl ? 1 : -1;
     98                $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
     99                for($x=$xl, $i=0; $i < $steps; ++$i) {
     100                    $this->img->current_color = $colors[$i];
     101                    $this->img->Line($x,$yb,$x,$yt);
     102                    $x += $delta;
     103                }
     104                --$i;
     105                if( abs($xr-$xl) % 2 == 1 ) --$steps;
     106                for($j=0; $j < $steps; ++$j, --$i) {
     107                    $this->img->current_color = $colors[$i];
     108                    $this->img->Line($x,$yb,$x,$yt);
     109                    $x += $delta;
     110                }
     111                $this->img->Line($x,$yb,$x,$yt);               
     112                break;
     113
     114            case GRAD_WIDE_MIDVER:
     115                $diff = ceil(abs($xr-$xl));
     116                $steps = floor(abs($diff)/3);
     117                $firststep = $diff - 2*$steps ;
     118                $delta = $xr >= $xl ? 1 : -1;
     119                $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
     120                for($x=$xl, $i=0; $i < $firststep; ++$i) {
     121                    $this->img->current_color = $colors[$i];
     122                    $this->img->Line($x,$yb,$x,$yt);
     123                    $x += $delta;
     124                }
     125                --$i;
     126                $this->img->current_color = $colors[$i];
     127                for($j=0; $j< $steps; ++$j) {
     128                    $this->img->Line($x,$yb,$x,$yt);
     129                    $x += $delta;
     130                }
     131               
     132                for($j=0; $j < $steps; ++$j, --$i) {
     133                    $this->img->current_color = $colors[$i];                           
     134                    $this->img->Line($x,$yb,$x,$yt);   
     135                    $x += $delta;
     136                }                               
     137                break;
     138
     139            case GRAD_WIDE_MIDHOR:
     140                $diff = ceil(abs($yb-$yt));
     141                $steps = floor(abs($diff)/3);
     142                $firststep = $diff - 2*$steps ;
     143                $delta = $yb >= $yt? 1 : -1;
     144                $this->GetColArray($from_color,$to_color,$firststep,$colors,$this->numcolors);
     145                for($y=$yt, $i=0; $i < $firststep;  ++$i) {
     146                    $this->img->current_color = $colors[$i];
     147                    $this->img->Line($xl,$y,$xr,$y);
     148                    $y += $delta;
     149                }
     150                --$i;
     151                $this->img->current_color = $colors[$i];
     152                for($j=0; $j < $steps; ++$j) {
     153                    $this->img->Line($xl,$y,$xr,$y);
     154                    $y += $delta;
     155                }
     156                for($j=0; $j < $steps; ++$j, --$i) {
     157                    $this->img->current_color = $colors[$i];                           
     158                    $this->img->Line($xl,$y,$xr,$y);
     159                    $y += $delta;
     160                }                               
     161                break;     
     162
     163            case GRAD_LEFT_REFLECTION:
     164                $steps1 = ceil(0.3*abs($xr-$xl));
     165                $delta = $xr>=$xl ? 1 : -1;             
     166
     167                $from_color = $this->img->rgb->Color($from_color);
     168                $adj = 1.4;
     169                $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2]))));
     170                $from_color2 = array(min(255,$from_color[0]+$m),
     171                                    min(255,$from_color[1]+$m), min(255,$from_color[2]+$m));           
     172
     173                $this->GetColArray($from_color2,$to_color,$steps1,$colors,$this->numcolors);
     174                $n = count($colors);
     175                for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
     176                    $this->img->current_color = $colors[$i];
     177                    $this->img->Line($x,$yb,$x,$yt);
     178                    $x += $delta;
     179                }
     180                $steps2 = max(1,ceil(0.08*abs($xr-$xl)));
     181                $this->img->SetColor($to_color);
     182                for($j=0; $j< $steps2; ++$j) {
     183                    $this->img->Line($x,$yb,$x,$yt);
     184                    $x += $delta;
     185                }
     186                $steps = abs($xr-$xl)-$steps1-$steps2;
     187                $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors);   
     188                $n = count($colors);
     189                for($i=0; $i < $steps && $i < $n; ++$i) {
     190                    $this->img->current_color = $colors[$i];
     191                    $this->img->Line($x,$yb,$x,$yt);
     192                    $x += $delta;
     193                }
     194                break;
     195
     196            case GRAD_RIGHT_REFLECTION:
     197                $steps1 = ceil(0.7*abs($xr-$xl));
     198                $delta = $xr>=$xl ? 1 : -1;
     199
     200                $this->GetColArray($from_color,$to_color,$steps1,$colors,$this->numcolors);
     201                $n = count($colors);
     202                for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
     203                    $this->img->current_color = $colors[$i];
     204                    $this->img->Line($x,$yb,$x,$yt);
     205                    $x += $delta;
     206                }
     207                $steps2 = max(1,ceil(0.08*abs($xr-$xl)));
     208                $this->img->SetColor($to_color);
     209                for($j=0; $j< $steps2; ++$j) {
     210                    $this->img->Line($x,$yb,$x,$yt);
     211                    $x += $delta;
     212                }
     213
     214                $from_color = $this->img->rgb->Color($from_color);
     215                $adj = 1.4;
     216                $m = ($adj-1.0)*(255-min(255,min($from_color[0],min($from_color[1],$from_color[2]))));
     217                $from_color = array(min(255,$from_color[0]+$m),
     218                                    min(255,$from_color[1]+$m), min(255,$from_color[2]+$m));           
     219
     220                $steps = abs($xr-$xl)-$steps1-$steps2;
     221                $this->GetColArray($to_color,$from_color,$steps,$colors,$this->numcolors);   
     222                $n = count($colors);
     223                for($i=0; $i < $steps && $i < $n; ++$i) {
     224                    $this->img->current_color = $colors[$i];
     225                    $this->img->Line($x,$yb,$x,$yt);
     226                    $x += $delta;
     227                }
     228                break;
     229
     230            case GRAD_CENTER:
     231                $steps = ceil(min(($yb-$yt)+1,($xr-$xl)+1)/2); 
     232                $this->GetColArray($from_color,$to_color,$steps,$colors,$this->numcolors);
     233                $dx = ($xr-$xl)/2;
     234                $dy = ($yb-$yt)/2;
     235                $x=$xl;$y=$yt;$x2=$xr;$y2=$yb;
     236                $n = count($colors);
     237                for($x=$xl, $i=0; $x < $xl+$dx && $y < $yt+$dy && $i < $n; ++$x, ++$y, --$x2, --$y2, ++$i) {
     238                    $this->img->current_color = $colors[$i];                   
     239                    $this->img->Rectangle($x,$y,$x2,$y2);
     240                }
     241                $this->img->Line($x,$y,$x2,$y2);
     242                break;
     243               
     244            case GRAD_RAISED_PANEL:
     245                // right to left
     246                $steps1 = $xr-$xl;
     247                $delta = $xr>=$xl ? 1 : -1;
     248                $this->GetColArray($to_color,$from_color,$steps1,$colors,$this->numcolors);
     249                $n = count($colors);
     250                for($x=$xl, $i=0; $i < $steps1 && $i < $n; ++$i) {
     251                    $this->img->current_color = $colors[$i];
     252                    $this->img->Line($x,$yb,$x,$yt);
     253                    $x += $delta;
     254                }
     255               
     256                // left to right
     257                $xr -= 3;
     258                $xl += 3;
     259                $yb -= 3;
     260                $yt += 3;
     261                $steps2 = $xr-$xl;
     262                $delta = $xr>=$xl ? 1 : -1;
     263                for($x=$xl, $j=$steps2; $j >= 0; --$j) {
     264                    $this->img->current_color = $colors[$j];
     265                    $this->img->Line($x,$yb,$x,$yt);
     266                    $x += $delta;
     267                }
     268                break;
     269
     270            case GRAD_DIAGONAL:
     271                // use the longer dimension to determine the required number of steps.
     272                // first loop draws from one corner to the mid-diagonal and the second
     273                // loop draws from the mid-diagonal to the opposing corner.
     274                if($xr-$xl > $yb - $yt) {
     275                    // width is greater than height -> use x-dimension for steps
     276                    $steps = $xr-$xl;
     277                    $delta = $xr>=$xl ? 1 : -1;
     278                    $this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors);
     279                    $n = count($colors);
     280
     281                    for($x=$xl, $i=0; $i < $steps && $i < $n; ++$i) {
     282                        $this->img->current_color = $colors[$i];
     283                        $y = $yt+($i/$steps)*($yb-$yt)*$delta;
     284                        $this->img->Line($x,$yt,$xl,$y);
     285                        $x += $delta;
     286                    }
     287
     288                    for($x=$xl, $i = 0; $i < $steps && $i < $n; ++$i) {
     289                        $this->img->current_color = $colors[$steps+$i];
     290                        $y = $yt+($i/$steps)*($yb-$yt)*$delta;
     291                        $this->img->Line($x,$yb,$xr,$y);
     292                        $x += $delta;
     293                    }
     294                } else {
     295                    // height is greater than width -> use y-dimension for steps
     296                    $steps = $yb-$yt;
     297                    $delta = $yb>=$yt ? 1 : -1;
     298                    $this->GetColArray($from_color,$to_color,$steps*2,$colors,$this->numcolors);
     299                    $n = count($colors);
     300                   
     301                    for($y=$yt, $i=0; $i < $steps && $i < $n; ++$i) {
     302                        $this->img->current_color = $colors[$i];
     303                        $x = $xl+($i/$steps)*($xr-$xl)*$delta;
     304                        $this->img->Line($x,$yt,$xl,$y);
     305                        $y += $delta;
     306                    }
     307
     308                    for($y=$yt, $i = 0; $i < $steps && $i < $n; ++$i) {
     309                        $this->img->current_color = $colors[$steps+$i];
     310                        $x = $xl+($i/$steps)*($xr-$xl)*$delta;
     311                        $this->img->Line($x,$yb,$xr,$y);
     312                        $x += $delta;
     313                    }
     314
     315                }
     316                break;
     317
     318            default:
     319                JpGraphError::RaiseL(7001,$style);
     320//("Unknown gradient style (=$style).");
     321                break;
     322        }
    328323    }
    329324
     
    334329    // of a mountain)
    335330    function FilledFlatPolygon($pts,$from_color,$to_color) {
    336         if( count($pts) == 0 ) return;
    337 
    338         $maxy=$pts[1];
    339         $miny=$pts[1];
    340         $n = count($pts) ;
    341         for( $i=0, $idx=0; $i < $n; $i += 2) {
    342             $x = round($pts[$i]);
    343             $y = round($pts[$i+1]);
    344             $miny = min($miny,$y);
    345             $maxy = max($maxy,$y);
    346         }
    347 
    348         $colors = array();
    349         $this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors);
    350         for($i=$miny, $idx=0; $i <= $maxy; ++$i ) {
    351             $colmap[$i] = $colors[$idx++];
    352         }
    353 
    354         $n = count($pts)/2 ;
    355         $idx = 0 ;
    356         while( $idx < $n-1 ) {
    357             $p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1]));
    358             $p2 = array(round($pts[++$idx*2]),round($pts[$idx*2+1]));
    359 
    360             // Find the largest rectangle we can fill
    361             $y = max($p1[1],$p2[1]) ;
    362             for($yy=$maxy; $yy > $y; --$yy) {
    363                 $this->img->current_color = $colmap[$yy];
    364                 $this->img->Line($p1[0],$yy,$p2[0]-1,$yy);
    365             }
    366 
    367             if( $p1[1] == $p2[1] ) {
    368                 continue;
    369             }
    370 
    371             // Fill the rest using lines (slow...)
    372             $slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]);
    373             $x1 = $p1[0];
    374             $x2 = $p2[0]-1;
    375             $start = $y;
    376             if( $p1[1] > $p2[1] ) {
    377                 while( $y >= $p2[1] ) {
    378                     $x1=$slope*($start-$y)+$p1[0];
    379                     $this->img->current_color = $colmap[$y];
    380                     $this->img->Line($x1,$y,$x2,$y);
    381                     --$y;
    382                 }
    383             }
    384             else {
    385                 while( $y >= $p1[1] ) {
    386                     $x2=$p2[0]+$slope*($start-$y);
    387                     $this->img->current_color = $colmap[$y];
    388                     $this->img->Line($x1,$y,$x2,$y);
    389                     --$y;
    390                 }
    391             }
    392         }
     331        if( count($pts) == 0 ) return;
     332       
     333        $maxy=$pts[1];
     334        $miny=$pts[1];         
     335        $n = count($pts) ;
     336        for( $i=0, $idx=0; $i < $n; $i += 2) {
     337            $x = round($pts[$i]);
     338            $y = round($pts[$i+1]);
     339            $miny = min($miny,$y);
     340            $maxy = max($maxy,$y);
     341        }
     342           
     343        $colors = array();
     344        $this->GetColArray($from_color,$to_color,abs($maxy-$miny)+1,$colors,$this->numcolors);
     345        for($i=$miny, $idx=0; $i <= $maxy; ++$i ) {
     346            $colmap[$i] = $colors[$idx++];
     347        }
     348
     349        $n = count($pts)/2 ;
     350        $idx = 0 ;
     351        while( $idx < $n-1 ) {
     352            $p1 = array(round($pts[$idx*2]),round($pts[$idx*2+1]));
     353            $p2 = array(round($pts[++$idx*2]),round($pts[$idx*2+1]));
     354               
     355            // Find the largest rectangle we can fill
     356            $y = max($p1[1],$p2[1]) ;
     357            for($yy=$maxy; $yy > $y; --$yy) {
     358                $this->img->current_color = $colmap[$yy];
     359                $this->img->Line($p1[0],$yy,$p2[0]-1,$yy);
     360            }
     361           
     362            if( $p1[1] == $p2[1] ) continue;
     363
     364            // Fill the rest using lines (slow...)
     365            $slope = ($p2[0]-$p1[0])/($p1[1]-$p2[1]);
     366            $x1 = $p1[0];
     367            $x2 = $p2[0]-1;
     368            $start = $y;
     369            if( $p1[1] > $p2[1] ) {
     370                while( $y >= $p2[1] ) {
     371                    $x1=$slope*($start-$y)+$p1[0];
     372                    $this->img->current_color = $colmap[$y];
     373                    $this->img->Line($x1,$y,$x2,$y);
     374                    --$y;
     375                }
     376            }
     377            else {
     378                while( $y >= $p1[1] ) {
     379                    $x2=$p2[0]+$slope*($start-$y);
     380                    $this->img->current_color = $colmap[$y];
     381                    $this->img->Line($x1,$y,$x2,$y);
     382                    --$y;
     383                }
     384            }
     385        }
    393386    }
    394387
    395     //---------------
    396     // PRIVATE METHODS
     388//---------------
     389// PRIVATE METHODS     
    397390    // Add to the image color map the necessary colors to do the transition
    398391    // between the two colors using $numcolors intermediate colors
    399392    function GetColArray($from_color,$to_color,$arr_size,&$colors,$numcols=100) {
    400         if( $arr_size==0 ) {
    401             return;
    402         }
    403 
    404         // If color is given as text get it's corresponding r,g,b values
    405         $from_color = $this->img->rgb->Color($from_color);
    406         $to_color = $this->img->rgb->Color($to_color);
    407 
    408         $rdelta=($to_color[0]-$from_color[0])/$numcols;
    409         $gdelta=($to_color[1]-$from_color[1])/$numcols;
    410         $bdelta=($to_color[2]-$from_color[2])/$numcols;
    411         $colorsperstep = $numcols/$arr_size;
    412         $prevcolnum = -1;
    413         $from_alpha = floatval($from_color[3]);
    414         $to_alpha = floatval($to_color[3]);
    415         $adelta = ( $to_alpha - $from_alpha ) / $numcols ;
    416         for ($i=0; $i < $arr_size; ++$i) {
    417             $colnum = floor($colorsperstep*$i);
    418             if ( $colnum == $prevcolnum ) {
    419                 $colors[$i] = $colidx;
    420             }
    421             else {
    422                 $r = floor($from_color[0] + $colnum*$rdelta);
    423                 $g = floor($from_color[1] + $colnum*$gdelta);
    424                 $b = floor($from_color[2] + $colnum*$bdelta);
    425                 $alpha = $from_alpha + $colnum*$adelta;
    426                 $colidx = $this->img->rgb->Allocate(sprintf("#%02x%02x%02x",$r,$g,$b),$alpha);
    427                 $colors[$i] = $colidx;
    428             }
    429             $prevcolnum = $colnum;
    430         }
    431     }
     393        if( $arr_size==0 ) return;
     394        // If color is given as text get it's corresponding r,g,b values
     395        $from_color = $this->img->rgb->Color($from_color);
     396        $to_color = $this->img->rgb->Color($to_color);
     397               
     398        $rdelta=($to_color[0]-$from_color[0])/$numcols;
     399        $gdelta=($to_color[1]-$from_color[1])/$numcols;
     400        $bdelta=($to_color[2]-$from_color[2])/$numcols;
     401        $colorsperstep  = $numcols/$arr_size;
     402        $prevcolnum     = -1;
     403        $from_alpha = $from_color[3];
     404        $to_alpha = $to_color[3];
     405        $adelta = ( $to_alpha - $from_alpha ) / $numcols ;
     406        for ($i=0; $i < $arr_size; ++$i) {
     407            $colnum = floor($colorsperstep*$i);
     408            if ( $colnum == $prevcolnum )
     409                $colors[$i]     = $colidx;
     410            else {
     411                $r = floor($from_color[0] + $colnum*$rdelta);
     412                $g = floor($from_color[1] + $colnum*$gdelta);
     413                $b = floor($from_color[2] + $colnum*$bdelta);
     414                $alpha = $from_alpha + $colnum*$adelta;
     415                $colidx = $this->img->rgb->Allocate(sprintf("#%02x%02x%02x",$r,$g,$b),$alpha);
     416                $colors[$i] = $colidx;
     417            }
     418            $prevcolnum = $colnum;
     419        }
     420    }   
    432421} // Class
    433422
  • trunk/client/modules/Elezioni/grafici/jpgraph_iconplot.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_ICONPLOT.PHP
    4 // Description: Extension module to add icons to plots
    5 // Created:     2004-02-18
    6 // Ver:         $Id: jpgraph_iconplot.php 1404 2009-06-28 15:25:41Z ljp $
     3// File:        JPGRAPH_ICONPLOT.PHP
     4// Description: PHP4 Graph Plotting library. Extension module.
     5// Created:     2004-02-18
     6// Ver:         $Id: jpgraph_iconplot.php 781 2006-10-08 08:07:47Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    2525
    2626
    27     function __construct($aFile="",$aX=0,$aY=0,$aScale=1.0,$aMix=100) {
    28         $this->iFile = $aFile;
    29         $this->iX=$aX;
    30         $this->iY=$aY;
    31         $this->iScale= $aScale;
    32         if( $aMix < 0 || $aMix > 100 ) {
    33             JpGraphError::RaiseL(8001); //('Mix value for icon must be between 0 and 100.');
    34         }
    35         $this->iMix = $aMix ;
     27    function IconPlot($aFile="",$aX=0,$aY=0,$aScale=1.0,$aMix=100) {
     28        $this->iFile = $aFile;
     29        $this->iX=$aX;
     30        $this->iY=$aY;
     31        $this->iScale= $aScale;
     32        if( $aMix < 0 || $aMix > 100 ) {
     33            JpGraphError::RaiseL(8001); //('Mix value for icon must be between 0 and 100.');
     34        }
     35        $this->iMix = $aMix ;
    3636    }
    3737
    3838    function SetCountryFlag($aFlag,$aX=0,$aY=0,$aScale=1.0,$aMix=100,$aStdSize=3) {
    39         $this->iCountryFlag = $aFlag;
    40         $this->iX=$aX;
    41         $this->iY=$aY;
    42         $this->iScale= $aScale;
    43         if( $aMix < 0 || $aMix > 100 ) {
    44             JpGraphError::RaiseL(8001);//'Mix value for icon must be between 0 and 100.');
    45         }
    46         $this->iMix = $aMix;
    47         $this->iCountryStdSize = $aStdSize;
     39        $this->iCountryFlag = $aFlag;
     40        $this->iX=$aX;
     41        $this->iY=$aY;
     42        $this->iScale= $aScale;
     43        if( $aMix < 0 || $aMix > 100 ) {
     44            JpGraphError::RaiseL(8001);//'Mix value for icon must be between 0 and 100.');
     45        }
     46        $this->iMix = $aMix;
     47        $this->iCountryStdSize = $aStdSize;
    4848    }
    4949
    5050    function SetPos($aX,$aY) {
    51         $this->iX=$aX;
    52         $this->iY=$aY;
     51        $this->iX=$aX;
     52        $this->iY=$aY;
    5353    }
    5454
    5555    function CreateFromString($aStr) {
    56         $this->iImgString = $aStr;
     56        $this->iImgString = $aStr;
    5757    }
    5858
    5959    function SetScalePos($aX,$aY) {
    60         $this->iScalePosX = $aX;
    61         $this->iScalePosY = $aY;
     60        $this->iScalePosX = $aX;
     61        $this->iScalePosY = $aY;
    6262    }
    6363
    6464    function SetScale($aScale) {
    65         $this->iScale = $aScale;
     65        $this->iScale = $aScale;
    6666    }
    6767
    6868    function SetMix($aMix) {
    69         if( $aMix < 0 || $aMix > 100 ) {
    70             JpGraphError::RaiseL(8001);//('Mix value for icon must be between 0 and 100.');
    71         }
    72         $this->iMix = $aMix ;
     69        if( $aMix < 0 || $aMix > 100 ) {
     70            JpGraphError::RaiseL(8001);//('Mix value for icon must be between 0 and 100.');
     71        }
     72        $this->iMix = $aMix ;
    7373    }
    7474
    7575    function SetAnchor($aXAnchor='left',$aYAnchor='center') {
    76         if( !in_array($aXAnchor,$this->iAnchors) ||
    77         !in_array($aYAnchor,$this->iAnchors) ) {
    78             JpGraphError::RaiseL(8002);//("Anchor position for icons must be one of 'top', 'bottom', 'left', 'right' or 'center'");
    79         }
    80         $this->iHorAnchor=$aXAnchor;
    81         $this->iVertAnchor=$aYAnchor;
     76        if( !in_array($aXAnchor,$this->iAnchors) ||
     77            !in_array($aYAnchor,$this->iAnchors) ) {
     78            JpGraphError::RaiseL(8002);//("Anchor position for icons must be one of 'top', 'bottom', 'left', 'right' or 'center'");
     79        }
     80        $this->iHorAnchor=$aXAnchor;
     81        $this->iVertAnchor=$aYAnchor;
    8282    }
    83 
     83   
    8484    function PreStrokeAdjust($aGraph) {
    85         // Nothing to do ...
     85        // Nothing to do ...
    8686    }
    8787
    8888    function DoLegend($aGraph) {
    89         // Nothing to do ...
     89        // Nothing to do ...
    9090    }
    9191
    9292    function Max() {
    93         return array(false,false);
     93        return array(false,false);
    9494    }
    9595
     
    105105
    106106    function Min() {
    107         return array(false,false);
     107        return array(false,false);
    108108    }
    109109
    110110    function StrokeMargin(&$aImg) {
    111         return true;
     111        return true;
    112112    }
    113113
    114     function Stroke($aImg,$axscale=null,$ayscale=null) {
    115         $this->StrokeWithScale($aImg,$axscale,$ayscale);
     114    function Stroke($aImg,$axscale,$ayscale) {
     115        $this->StrokeWithScale($aImg,$axscale,$ayscale);
    116116    }
    117117
    118118    function StrokeWithScale($aImg,$axscale,$ayscale) {
    119         if( $this->iScalePosX === null || $this->iScalePosY === null ||
    120                 $axscale === null || $ayscale === null ) {
    121             $this->_Stroke($aImg);
    122         }
    123         else {
    124             $this->_Stroke($aImg,
    125                 round($axscale->Translate($this->iScalePosX)),
    126                 round($ayscale->Translate($this->iScalePosY)));
    127         }
     119        if( $this->iScalePosX === null ||
     120            $this->iScalePosY === null ) {
     121            $this->_Stroke($aImg);
     122        }
     123        else {
     124            $this->_Stroke($aImg,
     125                          round($axscale->Translate($this->iScalePosX)),
     126                          round($ayscale->Translate($this->iScalePosY)));
     127        }
    128128    }
    129129
    130130    function GetWidthHeight() {
    131         $dummy=0;
    132         return $this->_Stroke($dummy,null,null,true);
     131        $dummy=0;
     132        return $this->_Stroke($dummy,null,null,true);
    133133    }
    134134
    135135    function _Stroke($aImg,$x=null,$y=null,$aReturnWidthHeight=false) {
    136         if( $this->iFile != '' && $this->iCountryFlag != '' ) {
    137             JpGraphError::RaiseL(8003);//('It is not possible to specify both an image file and a country flag for the same icon.');
    138         }
    139         if( $this->iFile != '' ) {
    140             $gdimg = Graph::LoadBkgImage('',$this->iFile);
    141         }
    142         elseif( $this->iImgString != '') {
    143             $gdimg = Image::CreateFromString($this->iImgString);
    144         }
     136        if( $this->iFile != '' && $this->iCountryFlag != '' ) {
     137            JpGraphError::RaiseL(8003);//('It is not possible to specify both an image file and a country flag for the same icon.');   
     138        }
     139        if( $this->iFile != '' ) {
     140            $gdimg = Graph::LoadBkgImage('',$this->iFile);
     141        }
     142        elseif( $this->iImgString != '') {
     143            $gdimg = Image::CreateFromString($this->iImgString);
     144        }
    145145
    146         else {
    147             if( ! class_exists('FlagImages',false) ) {
    148                 JpGraphError::RaiseL(8004);//('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.');
    149             }
    150             $fobj = new FlagImages($this->iCountryStdSize);
    151             $dummy='';
    152             $gdimg = $fobj->GetImgByName($this->iCountryFlag,$dummy);
    153         }
     146        else {
     147            if( ! class_exists('FlagImages',false) ) {
     148                JpGraphError::RaiseL(8004);//('In order to use Country flags as icons you must include the "jpgraph_flags.php" file.');
     149            }
     150            $fobj = new FlagImages($this->iCountryStdSize);
     151            $dummy='';
     152            $gdimg = $fobj->GetImgByName($this->iCountryFlag,$dummy);
     153        }
    154154
    155         $iconw = imagesx($gdimg);
    156         $iconh = imagesy($gdimg);
     155        $iconw = imagesx($gdimg);
     156        $iconh = imagesy($gdimg);
     157       
     158        if( $aReturnWidthHeight ) {
     159            return array(round($iconw*$this->iScale),round($iconh*$this->iScale));
     160        }
    157161
    158         if( $aReturnWidthHeight ) {
    159             return array(round($iconw*$this->iScale),round($iconh*$this->iScale));
    160         }
     162        if( $x !== null && $y !== null ) {
     163            $this->iX = $x; $this->iY = $y;
     164        }
     165        if( $this->iX >= 0  && $this->iX <= 1.0 ) {
     166            $w = imagesx($aImg->img);
     167            $this->iX = round($w*$this->iX);
     168        }
     169        if( $this->iY >= 0  && $this->iY <= 1.0 ) {
     170            $h = imagesy($aImg->img);
     171            $this->iY = round($h*$this->iY);
     172        }
    161173
    162         if( $x !== null && $y !== null ) {
    163             $this->iX = $x; $this->iY = $y;
    164         }
    165         if( $this->iX >= 0  && $this->iX <= 1.0 ) {
    166             $w = imagesx($aImg->img);
    167             $this->iX = round($w*$this->iX);
    168         }
    169         if( $this->iY >= 0  && $this->iY <= 1.0 ) {
    170             $h = imagesy($aImg->img);
    171             $this->iY = round($h*$this->iY);
    172         }
     174        if( $this->iHorAnchor == 'center' )
     175            $this->iX -= round($iconw*$this->iScale/2);
     176        if( $this->iHorAnchor == 'right' )
     177            $this->iX -= round($iconw*$this->iScale);
     178        if( $this->iVertAnchor == 'center' )
     179            $this->iY -= round($iconh*$this->iScale/2);
     180        if( $this->iVertAnchor == 'bottom' )
     181            $this->iY -= round($iconh*$this->iScale);
    173182
    174         if( $this->iHorAnchor == 'center' )
    175         $this->iX -= round($iconw*$this->iScale/2);
    176         if( $this->iHorAnchor == 'right' )
    177         $this->iX -= round($iconw*$this->iScale);
    178         if( $this->iVertAnchor == 'center' )
    179         $this->iY -= round($iconh*$this->iScale/2);
    180         if( $this->iVertAnchor == 'bottom' )
    181         $this->iY -= round($iconh*$this->iScale);
    182 
    183         $aImg->CopyMerge($gdimg,$this->iX,$this->iY,0,0,
    184         round($iconw*$this->iScale),round($iconh*$this->iScale),
    185         $iconw,$iconh,
    186         $this->iMix);
     183        $aImg->CopyMerge($gdimg,$this->iX,$this->iY,0,0,
     184                         round($iconw*$this->iScale),round($iconh*$this->iScale),
     185                         $iconw,$iconh,
     186                         $this->iMix);
    187187    }
    188188}
  • trunk/client/modules/Elezioni/grafici/jpgraph_imgtrans.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_IMGTRANS.PHP
    4 // Description: Extension for JpGraph to do some simple img transformations
    5 // Created:     2003-09-06
    6 // Ver:         $Id: jpgraph_imgtrans.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        JPGRAPH_IMGTRANS.PHP
     4// Description: Extension for JpGraph to do some simple img transformations
     5// Created:     2003-09-06
     6// Ver:         $Id: jpgraph_imgtrans.php 781 2006-10-08 08:07:47Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
    1111//------------------------------------------------------------------------
    1212// Class ImgTrans
    13 // Perform some simple image transformations.
     13// Perform some simple image transformations. 
    1414//------------------------------------------------------------------------
    1515class ImgTrans {
    1616    private $gdImg=null;
    1717
    18     function __construct($aGdImg) {
    19         // Constructor
    20         $this->gdImg = $aGdImg;
    21     }
    22 
    23     // --------------------------------------------------------------------
    24     // _TransVert3D() and _TransHor3D() are helper methods to
    25     // Skew3D().
     18    function ImgTrans($aGdImg) {
     19        // Constructor
     20        $this->gdImg = $aGdImg;
     21    }
     22
     23    // --------------------------------------------------------------------
     24    // _TransVert3D() and _TransHor3D() are helper methods to 
     25    // Skew3D(). 
    2626    // --------------------------------------------------------------------
    2727    function _TransVert3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_DOWN,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) {
    2828
    2929
    30         // Parameter check
    31     if( $aHorizonPos < 0 || $aHorizonPos > 1.0 ) {
    32         JpGraphError::RaiseL(9001);
    33         //("Value for image transformation out of bounds.\nVanishing point on horizon must be specified as a value between 0 and 1.");
    34     }
    35 
    36     $w = imagesx($aGdImg);
    37     $h = imagesy($aGdImg);
    38 
    39     // Create new image
    40     $ww = $w;
    41     if( $aMinSize )
    42     $hh = ceil($h * $aHorizon / ($aSkewDist+$h));
    43     else
    44     $hh = $h;
    45 
    46     $newgdh = imagecreatetruecolor($ww,$hh);
    47     $crgb = new RGB( $newgdh );
    48     $fillColor = $crgb->Allocate($aFillColor);
    49     imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor);
    50 
    51     if( $aBorder ) {
    52         $colidx = $crgb->Allocate($aBorder);
    53         imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx);
    54     }
    55 
    56     $mid = round($w * $aHorizonPos);
    57 
    58     $last=$h;
    59     for($y=0; $y < $h; ++$y) {
    60 
    61         $yp = $h-$y-1;
    62         $yt = floor($yp * $aHorizon / ($aSkewDist + $yp));
    63 
    64         if( !$aQuality ) {
    65             if( $last <= $yt ) continue ;
    66             $last = $yt;
    67         }
    68 
    69         for($x=0; $x < $w; ++$x) {
    70             $xt = ($x-$mid) * $aSkewDist / ($aSkewDist + $yp);
    71             if( $aDir == SKEW3D_UP )
    72             $rgb = imagecolorat($aGdImg,$x,$h-$y-1);
    73             else
    74             $rgb = imagecolorat($aGdImg,$x,$y);
    75             $r = ($rgb >> 16) & 0xFF;
    76             $g = ($rgb >> 8) & 0xFF;
    77             $b = $rgb & 0xFF;
    78             $colidx = imagecolorallocate($newgdh,$r,$g,$b);
    79             $xt = round($xt+$mid);
    80             if( $aDir == SKEW3D_UP ) {
    81                 $syt = $yt;
    82             }
    83             else {
    84                 $syt = $hh-$yt-1;
    85             }
    86 
    87             if( !empty($set[$yt]) ) {
    88                 $nrgb = imagecolorat($newgdh,$xt,$syt);
    89                 $nr = ($nrgb >> 16) & 0xFF;
    90                 $ng = ($nrgb >> 8) & 0xFF;
    91                 $nb = $nrgb & 0xFF;
    92                 $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2),
    93                 floor(($g+$ng)/2),floor(($b+$nb)/2));
    94             }
    95 
    96             imagesetpixel($newgdh,$xt,$syt,$colidx);
    97         }
    98 
    99         $set[$yt] = true;
    100     }
    101 
    102     return $newgdh;
    103     }
    104 
    105     // --------------------------------------------------------------------
    106     // _TransVert3D() and _TransHor3D() are helper methods to
    107     // Skew3D().
     30        // Parameter check
     31        if( $aHorizonPos < 0 || $aHorizonPos > 1.0 ) {
     32            JpGraphError::RaiseL(9001);
     33//("Value for image transformation out of bounds.\nVanishing point on horizon must be specified as a value between 0 and 1.");
     34        }
     35
     36        $w = imagesx($aGdImg);
     37        $h = imagesy($aGdImg);
     38
     39        // Create new image
     40        $ww = $w;
     41        if( $aMinSize )
     42            $hh = ceil($h * $aHorizon / ($aSkewDist+$h));
     43        else
     44            $hh = $h;
     45       
     46        $newgdh = imagecreatetruecolor($ww,$hh);
     47        $crgb = new RGB( $newgdh );
     48        $fillColor = $crgb->Allocate($aFillColor);
     49        imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor);
     50
     51        if( $aBorder ) {
     52            $colidx = $crgb->Allocate($aBorder);
     53            imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx);
     54        }
     55
     56        $mid = round($w * $aHorizonPos);
     57   
     58        $last=$h;
     59        for($y=0; $y < $h; ++$y) {     
     60
     61            $yp = $h-$y-1;
     62            $yt = floor($yp * $aHorizon / ($aSkewDist + $yp));     
     63
     64            if( !$aQuality ) {
     65                if( $last <= $yt ) continue ;
     66                $last = $yt;
     67            }
     68
     69            for($x=0; $x < $w; ++$x) {     
     70                $xt = ($x-$mid) * $aSkewDist / ($aSkewDist + $yp);
     71                if( $aDir == SKEW3D_UP )
     72                    $rgb = imagecolorat($aGdImg,$x,$h-$y-1);
     73                else
     74                    $rgb = imagecolorat($aGdImg,$x,$y);
     75                $r = ($rgb >> 16) & 0xFF;
     76                $g = ($rgb >> 8) & 0xFF;
     77                $b = $rgb & 0xFF;   
     78                $colidx = imagecolorallocate($newgdh,$r,$g,$b);
     79                $xt = round($xt+$mid);
     80                if( $aDir == SKEW3D_UP ) {
     81                    $syt = $yt;
     82                }
     83                else {
     84                    $syt = $hh-$yt-1;
     85                }
     86
     87                if( !empty($set[$yt]) ) {
     88                    $nrgb = imagecolorat($newgdh,$xt,$syt);
     89                    $nr = ($nrgb >> 16) & 0xFF;
     90                    $ng = ($nrgb >> 8) & 0xFF;
     91                    $nb = $nrgb & 0xFF;   
     92                    $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2),
     93                                                 floor(($g+$ng)/2),floor(($b+$nb)/2)); 
     94                }       
     95
     96                imagesetpixel($newgdh,$xt,$syt,$colidx);       
     97            }
     98
     99            $set[$yt] = true;   
     100        }
     101
     102        return $newgdh;
     103    }
     104
     105    // --------------------------------------------------------------------
     106    // _TransVert3D() and _TransHor3D() are helper methods to 
     107    // Skew3D(). 
    108108    // --------------------------------------------------------------------
    109109    function _TransHor3D($aGdImg,$aHorizon=100,$aSkewDist=120,$aDir=SKEW3D_LEFT,$aMinSize=true,$aFillColor='#FFFFFF',$aQuality=false,$aBorder=false,$aHorizonPos=0.5) {
    110110
    111         $w = imagesx($aGdImg);
    112         $h = imagesy($aGdImg);
    113 
    114         // Create new image
    115         $hh = $h;
    116         if( $aMinSize )
    117         $ww = ceil($w * $aHorizon / ($aSkewDist+$w));
    118         else
    119         $ww = $w;
    120 
    121         $newgdh = imagecreatetruecolor($ww,$hh);
    122         $crgb = new RGB( $newgdh );
    123         $fillColor = $crgb->Allocate($aFillColor);
    124         imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor);
    125 
    126         if( $aBorder ) {
    127             $colidx = $crgb->Allocate($aBorder);
    128             imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx);
    129         }
    130 
    131         $mid = round($h * $aHorizonPos);
    132 
    133         $last = -1;
    134         for($x=0; $x < $w-1; ++$x) {
    135             $xt = floor($x * $aHorizon / ($aSkewDist + $x));
    136             if( !$aQuality ) {
    137                 if( $last >= $xt ) continue ;
    138                 $last = $xt;
    139             }
    140 
    141             for($y=0; $y < $h; ++$y) {
    142                 $yp = $h-$y-1;
    143                 $yt = ($yp-$mid) * $aSkewDist / ($aSkewDist + $x);
    144 
    145                 if( $aDir == SKEW3D_RIGHT )
    146                 $rgb = imagecolorat($aGdImg,$w-$x-1,$y);
    147                 else
    148                 $rgb = imagecolorat($aGdImg,$x,$y);
    149                 $r = ($rgb >> 16) & 0xFF;
    150                 $g = ($rgb >> 8) & 0xFF;
    151                 $b = $rgb & 0xFF;
    152                 $colidx = imagecolorallocate($newgdh,$r,$g,$b);
    153                 $yt = floor($hh-$yt-$mid-1);
    154                 if( $aDir == SKEW3D_RIGHT ) {
    155                     $sxt = $ww-$xt-1;
    156                 }
    157                 else
    158                 $sxt = $xt ;
    159 
    160                 if( !empty($set[$xt]) ) {
    161                     $nrgb = imagecolorat($newgdh,$sxt,$yt);
    162                     $nr = ($nrgb >> 16) & 0xFF;
    163                     $ng = ($nrgb >> 8) & 0xFF;
    164                     $nb = $nrgb & 0xFF;
    165                     $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2),
    166                     floor(($g+$ng)/2),floor(($b+$nb)/2));
    167                 }
    168                 imagesetpixel($newgdh,$sxt,$yt,$colidx);
    169             }
    170 
    171             $set[$xt] = true;
    172         }
    173 
    174         return $newgdh;
     111        $w = imagesx($aGdImg);
     112        $h = imagesy($aGdImg);
     113
     114        // Create new image
     115        $hh = $h;
     116        if( $aMinSize )
     117            $ww = ceil($w * $aHorizon / ($aSkewDist+$w));
     118        else
     119            $ww = $w;
     120       
     121        $newgdh = imagecreatetruecolor($ww,$hh);
     122        $crgb = new RGB( $newgdh );
     123        $fillColor = $crgb->Allocate($aFillColor);
     124        imagefilledrectangle($newgdh,0,0,$ww-1,$hh-1,$fillColor);
     125
     126        if( $aBorder ) {
     127            $colidx = $crgb->Allocate($aBorder);
     128            imagerectangle($newgdh,0,0,$ww-1,$hh-1,$colidx);
     129        }
     130
     131        $mid = round($h * $aHorizonPos);
     132
     133        $last = -1;
     134        for($x=0; $x < $w-1; ++$x) {       
     135            $xt = floor($x * $aHorizon / ($aSkewDist + $x));
     136            if( !$aQuality ) {
     137                if( $last >= $xt ) continue ;
     138                $last = $xt;
     139            }
     140
     141            for($y=0; $y < $h; ++$y) { 
     142                $yp = $h-$y-1;
     143                $yt = ($yp-$mid) * $aSkewDist / ($aSkewDist + $x);
     144
     145                if( $aDir == SKEW3D_RIGHT )
     146                    $rgb = imagecolorat($aGdImg,$w-$x-1,$y);
     147                else
     148                    $rgb = imagecolorat($aGdImg,$x,$y);
     149                $r = ($rgb >> 16) & 0xFF;
     150                $g = ($rgb >> 8) & 0xFF;
     151                $b = $rgb & 0xFF;   
     152                $colidx = imagecolorallocate($newgdh,$r,$g,$b);
     153                $yt = floor($hh-$yt-$mid-1);
     154                if( $aDir == SKEW3D_RIGHT ) {
     155                    $sxt = $ww-$xt-1;
     156                }
     157                else
     158                    $sxt = $xt ;
     159
     160                if( !empty($set[$xt]) ) {
     161                    $nrgb = imagecolorat($newgdh,$sxt,$yt);
     162                    $nr = ($nrgb >> 16) & 0xFF;
     163                    $ng = ($nrgb >> 8) & 0xFF;
     164                    $nb = $nrgb & 0xFF;   
     165                    $colidx = imagecolorallocate($newgdh,floor(($r+$nr)/2),
     166                                                 floor(($g+$ng)/2),floor(($b+$nb)/2)); 
     167                }
     168                imagesetpixel($newgdh,$sxt,$yt,$colidx);       
     169            }
     170
     171            $set[$xt] = true;
     172        }
     173
     174        return $newgdh;
    175175    }
    176176
     
    180180    // of the image. The transformation is specified by giving the height
    181181    // of the artificial horizon and specifying a "skew" factor which
    182     // is the distance on the horizon line between the point of
     182    // is the distance on the horizon line between the point of 
    183183    // convergence and perspective line.
    184184    //
     
    188188    // Parameters:
    189189    // * $aGdImg, GD handle to the image to be transformed
    190     // * $aHorizon, Distance to the horizon
     190    // * $aHorizon, Distance to the horizon 
    191191    // * $aSkewDist, Distance from the horizon point of convergence
    192     //   on the horizon line to the perspective points. A larger
     192    //   on the horizon line to the perspective points. A larger 
    193193    //   value will fore-shorten the image more
    194     // * $aDir, parameter specifies type of convergence. This of this
     194    // * $aDir, parameter specifies type of convergence. This of this 
    195195    //   as the walls in a room you are looking at. This specifies if the
    196196    //   image should be applied on the left,right,top or bottom walls.
     
    202202    //   high quality will have a dramatic effect on the time it takes
    203203    //   to transform an image.
    204     // * $aBorder, if set to anything besides false this will draw a
     204    // * $aBorder, if set to anything besides false this will draw a 
    205205    //   a border of the speciied color around the image
    206206    // --------------------------------------------------------------------
    207207    function Skew3D($aHorizon=120,$aSkewDist=150,$aDir=SKEW3D_DOWN,$aHiQuality=false,$aMinSize=true,$aFillColor='#FFFFFF',$aBorder=false) {
    208         return $this->_Skew3D($this->gdImg,$aHorizon,$aSkewDist,$aDir,$aHiQuality,
    209         $aMinSize,$aFillColor,$aBorder);
     208        return $this->_Skew3D($this->gdImg,$aHorizon,$aSkewDist,$aDir,$aHiQuality,
     209                              $aMinSize,$aFillColor,$aBorder);
    210210    }
    211211
    212212    function _Skew3D($aGdImg,$aHorizon=120,$aSkewDist=150,$aDir=SKEW3D_DOWN,$aHiQuality=false,$aMinSize=true,$aFillColor='#FFFFFF',$aBorder=false) {
    213         if( $aDir == SKEW3D_DOWN || $aDir == SKEW3D_UP )
    214         return $this->_TransVert3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder);
    215         else
    216         return $this->_TransHor3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder);
    217 
    218     }
    219 
     213        if( $aDir == SKEW3D_DOWN || $aDir == SKEW3D_UP )
     214            return $this->_TransVert3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder);
     215        else
     216            return $this->_TransHor3D($aGdImg,$aHorizon,$aSkewDist,$aDir,$aMinSize,$aFillColor,$aHiQuality,$aBorder);
     217
     218    }
     219   
    220220}
    221221
  • trunk/client/modules/Elezioni/grafici/jpgraph_led.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_LED.PHP
    4 // Description: Module to generate Dotted LED-like digits
    5 // Created:     2006-11-26
    6 // Ver:         $Id: jpgraph_led.php 1674 2009-07-22 19:42:23Z ljp $
    7 //
    8 // Copyright 2006 (c) Asial Corporation. All rights reserved.
     3// File:        JPGRAPH_LED.PHP
     4// Description: Module to generate Dotted LED-like digits
     5// Created:     2006-11-26
     6// Ver:         $Id: jpgraph_led.php 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright 2006 (c) Aditus Consulting. All rights reserved.
    99//
    1010// Changed: 2007-08-06 by Alexander Kurochkin (inspector@list.ru)
     11// Added: Decipher 4-bit mask.
     12// Added: Chars Latin > 'L', Cyrilic, other symbols and special symbols for
     13//        simulation some latin and cyrilic chars.
     14// Added: New Color schemas.
     15// Deleted: Some minor bugs (StrokeNumber first parameter may be eq empty string,
     16//      false or null - added check see line 294;
     17//      change color schema check for easy maintenance: 291;
     18//      change check on key exist in chars array: moved from StrokeNumber
     19//      function to _GetLED: 251;
     20//
    1121//========================================================================
    1222
    13 // Constants for color schema
    14 DEFINE('LEDC_RED', 0);
    15 DEFINE('LEDC_GREEN', 1);
    16 DEFINE('LEDC_BLUE', 2);
    17 DEFINE('LEDC_YELLOW', 3);
    18 DEFINE('LEDC_GRAY', 4);
    19 DEFINE('LEDC_CHOCOLATE', 5);
    20 DEFINE('LEDC_PERU', 6);
    21 DEFINE('LEDC_GOLDENROD', 7);
    22 DEFINE('LEDC_KHAKI', 8);
    23 DEFINE('LEDC_OLIVE', 9);
    24 DEFINE('LEDC_LIMEGREEN', 10);
    25 DEFINE('LEDC_FORESTGREEN', 11);
    26 DEFINE('LEDC_TEAL', 12);
    27 DEFINE('LEDC_STEELBLUE', 13);
    28 DEFINE('LEDC_NAVY', 14);
    29 DEFINE('LEDC_INVERTGRAY', 15);
    30 
    31 // Check that mb_strlen() is available
    32 if( ! function_exists('mb_strlen') ) {
    33     JpGraphError::RaiseL(25500);
    34     //'Multibyte strings must be enabled in the PHP installation in order to run the LED module
    35     // so that the function mb_strlen() is available. See PHP documentation for more information.'
    36 }
     23// Samples for troubled chars: "Ô¡ Ø\r Ù\r Û| ÞÎ Ì\r >\n< W\r"
     24//                                                              Ô  Ø   Ù   Û  Þ  Ì   Æ    W
     25
     26//----------------------------------------------------------------------------
     27// Each character is encoded line by line with the "On"-LEDs corresponding to
     28// a '1' in the bianry mask of 4 bits.
     29//
     30// 4-bit mask:
     31//
     32// 0    ____
     33// 1    ___x
     34// 2    __x_
     35// 3    __xx
     36// 4    _x__
     37// 5    _x_x
     38// 6    _xx_
     39// 7    _xxx
     40// 8    x___
     41// 9    x__x
     42// 10   x_x_
     43// 11   x_xx
     44// 12   xx__
     45// 13   xx_x
     46// 14   xxx_
     47// 15   xxxx
     48//----------------------------------------------------------------------------
     49
     50// Constants for color schema. See definition of iColorSchema below
     51define('LEDC_RED', 0);
     52define('LEDC_GREEN', 1);
     53define('LEDC_BLUE', 2);
     54define('LEDC_YELLOW', 3);
     55define('LEDC_GRAY', 4);
     56define('LEDC_CHOCOLATE', 5);
     57define('LEDC_PERU', 6);
     58define('LEDC_GOLDENROD', 7);
     59define('LEDC_KHAKI', 8);
     60define('LEDC_OLIVE', 9);
     61define('LEDC_LIMEGREEN', 10);
     62define('LEDC_FORESTGREEN', 11);
     63define('LEDC_TEAL', 12);
     64define('LEDC_STEELBLUE', 13);
     65define('LEDC_NAVY', 14);
     66define('LEDC_INVERTGRAY', 15);
     67// ! It correlate with two-dimensional array $iColorSchema
    3768
    3869//========================================================================
    3970// CLASS DigitalLED74
    40 // Description:
     71// Description: 
    4172// Construct a number as an image that looks like LED numbers in a
    4273// 7x4 digital matrix
     
    4677    private $iLED_X = 4, $iLED_Y=7,
    4778
    48         // fg-up, fg-down, bg
    49         $iColorSchema = array(
    50             LEDC_RED  => array('red','darkred:0.9','red:0.3'),// 0
    51             LEDC_GREEN  => array('green','darkgreen','green:0.3'),// 1
    52             LEDC_BLUE  => array('lightblue:0.9','darkblue:0.85','darkblue:0.7'),// 2
    53             LEDC_YELLOW  => array('yellow','yellow:0.4','yellow:0.3'),// 3
    54             LEDC_GRAY  => array('gray:1.4','darkgray:0.85','darkgray:0.7'),
    55             LEDC_CHOCOLATE => array('chocolate','chocolate:0.7','chocolate:0.5'),
    56             LEDC_PERU  => array('peru:0.95','peru:0.6','peru:0.5'),
    57             LEDC_GOLDENROD => array('goldenrod','goldenrod:0.6','goldenrod:0.5'),
    58             LEDC_KHAKI  => array('khaki:0.7','khaki:0.4','khaki:0.3'),
    59             LEDC_OLIVE  => array('#808000','#808000:0.7','#808000:0.6'),
    60             LEDC_LIMEGREEN => array('limegreen:0.9','limegreen:0.5','limegreen:0.4'),
    61             LEDC_FORESTGREEN => array('forestgreen','forestgreen:0.7','forestgreen:0.5'),
    62             LEDC_TEAL  => array('teal','teal:0.7','teal:0.5'),
    63             LEDC_STEELBLUE => array('steelblue','steelblue:0.65','steelblue:0.5'),
    64             LEDC_NAVY  => array('navy:1.3','navy:0.95','navy:0.8'),//14
    65             LEDC_INVERTGRAY => array('darkgray','lightgray:1.5','white')//15
    66             ),
    67 
    68         /* Each line of the character is encoded as a 4 bit value
    69          0      ____
    70          1      ___x
    71          2      __x_
    72          3      __xx
    73          4      _x__
    74          5      _x_x
    75          6      _xx_
    76          7      _xxx
    77          8      x___
    78          9      x__x
    79          10     x_x_
    80          11     x_xx
    81          12     xx__
    82          13     xx_x
    83          14     xxx_
    84          15     xxxx
    85         */
    86 
    87         $iLEDSpec = array(
    88             0 => array(6,9,11,15,13,9,6),
    89             1 => array(2,6,10,2,2,2,2),
    90             2 => array(6,9,1,2,4,8,15),
    91             3 => array(6,9,1,6,1,9,6),
    92             4 => array(1,3,5,9,15,1,1),
    93             5 => array(15,8,8,14,1,9,6),
    94             6 => array(6,8,8,14,9,9,6),
    95             7 => array(15,1,1,2,4,4,4),
    96             8 => array(6,9,9,6,9,9,6),
    97             9 => array(6,9,9,7,1,1,6),
    98             '!' => array(4,4,4,4,4,0,4),
    99             '?' => array(6,9,1,2,2,0,2),
    100             '#' => array(0,9,15,9,15,9,0),
    101             '@' => array(6,9,11,11,10,9,6),
    102             '-' => array(0,0,0,15,0,0,0),
    103             '_' => array(0,0,0,0,0,0,15),
    104             '=' => array(0,0,15,0,15,0,0),
    105             '+' => array(0,0,4,14,4,0,0),
    106             '|' => array(4,4,4,4,4,4,4), //vertical line, used for simulate rus 'Ы'
    107             ',' => array(0,0,0,0,0,12,4),
    108             '.' => array(0,0,0,0,0,12,12),
    109             ':' => array(12,12,0,0,0,12,12),
    110             ';' => array(12,12,0,0,0,12,4),
    111             '[' => array(3,2,2,2,2,2,3),
    112             ']' => array(12,4,4,4,4,4,12),
    113             '(' => array(1,2,2,2,2,2,1),
    114             ')' => array(8,4,4,4,4,4,8),
    115             '{' => array(3,2,2,6,2,2,3),
    116             '}' => array(12,4,4,6,4,4,12),
    117             '<' => array(1,2,4,8,4,2,1),
    118             '>' => array(8,4,2,1,2,4,8),
    119             '*' => array(9,6,15,6,9,0,0),
    120             '"' => array(10,10,0,0,0,0,0),
    121             '\'' => array(4,4,0,0,0,0,0),
    122             '`' => array(4,2,0,0,0,0,0),
    123             '~' => array(13,11,0,0,0,0,0),
    124             '^' => array(4,10,0,0,0,0,0),
    125             '\\' => array(8,8,4,6,2,1,1),
    126             '/' => array(1,1,2,6,4,8,8),
    127             '%' => array(1,9,2,6,4,9,8),
    128             '&' => array(0,4,10,4,11,10,5),
    129             '$' => array(2,7,8,6,1,14,4),
    130             ' ' => array(0,0,0,0,0,0,0),
    131             '•' => array(0,0,6,6,0,0,0), //149
    132             '°' => array(14,10,14,0,0,0,0), //176
    133             '†' => array(4,4,14,4,4,4,4), //134
    134             '‡' => array(4,4,14,4,14,4,4), //135
    135             '±' => array(0,4,14,4,0,14,0), //177
    136             '‰' => array(0,4,2,15,2,4,0), //137 show right arrow
    137             '™' => array(0,2,4,15,4,2,0), //156 show left arrow
    138             'Ў' => array(0,0,8,8,0,0,0), //159 show small hi-stick - that need for simulate rus 'Ѐ'
    139             "\t" => array(8,8,8,0,0,0,0), //show hi-stick - that need for simulate rus 'У'
    140             "\r" => array(8,8,8,8,8,8,8), //vertical line - that need for simulate 'M', 'W' and rus 'М','К' ,'Щ'
    141             "\n" => array(15,15,15,15,15,15,15), //fill up - that need for simulate rus 'Ж'
    142             "Ґ" => array(10,5,10,5,10,5,10), //chess
    143             "µ" => array(15,0,15,0,15,0,15), //4 horizontal lines
    144             // latin
    145             'A' => array(6,9,9,15,9,9,9),
    146             'B' => array(14,9,9,14,9,9,14),
    147             'C' => array(6,9,8,8,8,9,6),
    148             'D' => array(14,9,9,9,9,9,14),
    149             'E' => array(15,8,8,14,8,8,15),
    150             'F' => array(15,8,8,14,8,8,8),
    151             'G' => array(6,9,8,8,11,9,6),
    152             'H' => array(9,9,9,15,9,9,9),
    153             'I' => array(14,4,4,4,4,4,14),
    154             'J' => array(15,1,1,1,1,9,6),
    155             'K' => array(8,9,10,12,12,10,9),
    156             'L' => array(8,8,8,8,8,8,15),
    157             'M' => array(8,13,10,8,8,8,8),// need to add \r
    158             'N' => array(9,9,13,11,9,9,9),
    159             'O' => array(6,9,9,9,9,9,6),
    160             'P' => array(14,9,9,14,8,8,8),
    161             'Q' => array(6,9,9,9,13,11,6),
    162             'R' => array(14,9,9,14,12,10,9),
    163             'S' => array(6,9,8,6,1,9,6),
    164             'T' => array(14,4,4,4,4,4,4),
    165             'U' => array(9,9,9,9,9,9,6),
    166             'V' => array(0,0,0,10,10,10,4),
    167             'W' => array(8,8,8,8,10,13,8),// need to add \r
    168             'X' => array(9,9,6,6,6,9,9),
    169             'Y' => array(10,10,10,10,4,4,4),
    170             'Z' => array(15,1,2,6,4,8,15),
    171             // russian utf-8
    172             'А' => array(6,9,9,15,9,9,9),
    173             'Б' => array(14,8,8,14,9,9,14),
    174             'В' => array(14,9,9,14,9,9,14),
    175             'Г' => array(15,8,8,8,8,8,8),
    176             'Д' => array(14,9,9,9,9,9,14),
    177             'Е' => array(15,8,8,14,8,8,15),
    178             'Ё' => array(6,15,8,14,8,8,15),
    179             //Ж is combine: >\n<
    180             'З' => array(6,9,1,2,1,9,6),
    181             'И' => array(9,9,9,11,13,9,9),
    182             'Й' => array(13,9,9,11,13,9,9),
    183             'К' => array(9,10,12,10,9,9,9),
    184             'Л' => array(7,9,9,9,9,9,9),
    185             'М' => array(8,13,10,8,8,8,8),// need to add \r
    186             'Н' => array(9,9,9,15,9,9,9),
    187             'О' => array(6,9,9,9,9,9,6),
    188             'П' => array(15,9,9,9,9,9,9),
    189             'Р' => array(14,9,9,14,8,8,8),
    190             'С' => array(6,9,8,8,8,9,6),
    191             'Т' => array(14,4,4,4,4,4,4),
    192             'У' => array(9,9,9,7,1,9,6),
    193             'Ѐ' => array(2,7,10,10,7,2,2),// need to add Ў
    194             'Ð¥' => array(9,9,6,6,6,9,9),
    195             'Њ' => array(10,10,10,10,10,15,1),
    196             'Ч' => array(9,9,9,7,1,1,1),
    197             'К' => array(10,10,10,10,10,10,15),// \r
    198             'Щ' => array(10,10,10,10,10,15,0),// need to add \r
    199             'Ъ' => array(12,4,4,6,5,5,6),
    200             'Ы' => array(8,8,8,14,9,9,14),// need to add |
    201             'Ь' => array(8,8,8,14,9,9,14),
    202             'Э' => array(6,9,1,7,1,9,6),
    203             'Ю' => array(2,2,2,3,2,2,2),// need to add O
    204             'Я' => array(7,9,9,7,3,5,9)
    205             ),
    206 
    207         $iSuperSampling = 3, $iMarg = 1, $iRad = 4;
    208 
    209     function __construct($aRadius = 2, $aMargin= 0.6) {
    210         $this->iRad = $aRadius;
    211         $this->iMarg = $aMargin;
     79        // fg-up, fg-down, bg
     80        $iColorSchema = array(
     81            LEDC_RED            => array('red','darkred:0.9','red:0.3'),// 0
     82            LEDC_GREEN          => array('green','darkgreen','green:0.3'),// 1
     83            LEDC_BLUE           => array('lightblue:0.9','darkblue:0.85','darkblue:0.7'),// 2
     84            LEDC_YELLOW         => array('yellow','yellow:0.4','yellow:0.3'),// 3
     85            LEDC_GRAY           => array('gray:1.4','darkgray:0.85','darkgray:0.7'),
     86            LEDC_CHOCOLATE      => array('chocolate','chocolate:0.7','chocolate:0.5'),
     87            LEDC_PERU           => array('peru:0.95','peru:0.6','peru:0.5'),
     88            LEDC_GOLDENROD      => array('goldenrod','goldenrod:0.6','goldenrod:0.5'),
     89            LEDC_KHAKI          => array('khaki:0.7','khaki:0.4','khaki:0.3'),
     90            LEDC_OLIVE          => array('#808000','#808000:0.7','#808000:0.6'),
     91            LEDC_LIMEGREEN      => array('limegreen:0.9','limegreen:0.5','limegreen:0.4'),
     92            LEDC_FORESTGREEN    => array('forestgreen','forestgreen:0.7','forestgreen:0.5'),
     93            LEDC_TEAL           => array('teal','teal:0.7','teal:0.5'),
     94            LEDC_STEELBLUE      => array('steelblue','steelblue:0.65','steelblue:0.5'),
     95            LEDC_NAVY           => array('navy:1.3','navy:0.95','navy:0.8'),//14
     96            LEDC_INVERTGRAY     => array('darkgray','lightgray:1.5','white')//15
     97            ),
     98
     99        $iLEDSpec = array(
     100            0 => array(6,9,11,15,13,9,6),
     101            //0 => array(6,9,9,9,9,9,6),
     102            //0 => array(15,9,9,9,9,9,15),
     103            1 => array(2,6,10,2,2,2,2),
     104            2 => array(6,9,1,2,4,8,15),
     105            3 => array(6,9,1,6,1,9,6),
     106            4 => array(1,3,5,9,15,1,1),
     107            5 => array(15,8,8,14,1,9,6),
     108            6 => array(6,8,8,14,9,9,6),
     109            7 => array(15,1,1,2,4,4,4),
     110            8 => array(6,9,9,6,9,9,6),
     111            9 => array(6,9,9,7,1,1,6),
     112            '!' => array(4,4,4,4,4,0,4),
     113            '?' => array(6,9,1,2,2,0,2),
     114            '#' => array(0,9,15,9,15,9,0),
     115            '@' => array(6,9,11,11,10,9,6),
     116            '-' => array(0,0,0,15,0,0,0),
     117            '_' => array(0,0,0,0,0,0,15),
     118            '=' => array(0,0,15,0,15,0,0),
     119            '+' => array(0,0,4,14,4,0,0),
     120            '|' => array(4,4,4,4,4,4,4), //vertical line, used for simulate rus 'Û'
     121            ',' => array(0,0,0,0,0,12,4),
     122            '.' => array(0,0,0,0,0,12,12),
     123            ':' => array(12,12,0,0,0,12,12),
     124            ';' => array(12,12,0,0,0,12,4),
     125            '[' => array(3,2,2,2,2,2,3),
     126            ']' => array(12,4,4,4,4,4,12),
     127            '(' => array(1,2,2,2,2,2,1),
     128            ')' => array(8,4,4,4,4,4,8),
     129            '{' => array(3,2,2,6,2,2,3),
     130            '}' => array(12,4,4,6,4,4,12),
     131            '<' => array(1,2,4,8,4,2,1),
     132            '>' => array(8,4,2,1,2,4,8),
     133            '*' => array(9,6,15,6,9,0,0),
     134            '"' => array(10,10,0,0,0,0,0),
     135            '\'' => array(4,4,0,0,0,0,0),
     136            '`' => array(4,2,0,0,0,0,0),
     137            '~' => array(13,11,0,0,0,0,0),
     138            '^' => array(4,10,0,0,0,0,0),
     139            '\\' => array(8,8,4,6,2,1,1),
     140            '/' => array(1,1,2,6,4,8,8),
     141            '%' => array(1,9,2,6,4,9,8),
     142            '&' => array(0,4,10,4,11,10,5),
     143            '$' => array(2,7,8,6,1,14,4),
     144            ' ' => array(0,0,0,0,0,0,0),
     145            '•' => array(0,0,6,6,0,0,0), //149
     146            '°' => array(14,10,14,0,0,0,0), //176
     147            '†' => array(4,4,14,4,4,4,4), //134
     148            '‡' => array(4,4,14,4,14,4,4), //135
     149            '±' => array(0,4,14,4,0,14,0), //177
     150            '‰' => array(0,4,2,15,2,4,0), //137 show right arrow
     151            '™' => array(0,2,4,15,4,2,0), //156 show left arrow
     152            '¡' => array(0,0,8,8,0,0,0), //159 show small hi-stick - that need for simulate rus 'Ô'
     153            "\t" => array(8,8,8,0,0,0,0), //show hi-stick - that need for simulate rus 'Ó'
     154            "\r" => array(8,8,8,8,8,8,8), //vertical line - that need for simulate 'M', 'W' and rus 'Ì','Ø' ,'Ù'
     155            "\n" => array(15,15,15,15,15,15,15), //fill up - that need for simulate rus 'Æ'
     156            "¥" => array(10,5,10,5,10,5,10), //chess
     157            "µ" => array(15,0,15,0,15,0,15), //4 horizontal lines
     158// latin
     159            'A' => array(6,9,9,15,9,9,9),
     160            'B' => array(14,9,9,14,9,9,14),
     161            'C' => array(6,9,8,8,8,9,6),
     162            'D' => array(14,9,9,9,9,9,14),
     163            'E' => array(15,8,8,14,8,8,15),
     164            'F' => array(15,8,8,14,8,8,8),
     165            'G' => array(6,9,8,8,11,9,6),
     166            'H' => array(9,9,9,15,9,9,9),
     167            'I' => array(14,4,4,4,4,4,14),
     168            'J' => array(15,1,1,1,1,9,6),
     169            'K' => array(8,9,10,12,12,10,9),
     170            'L' => array(8,8,8,8,8,8,15),
     171            'M' => array(8,13,10,8,8,8,8),// need to add \r
     172            'N' => array(9,9,13,11,9,9,9),
     173            //'O' => array(0,6,9,9,9,9,6),
     174            'O' => array(6,9,9,9,9,9,6),
     175            'P' => array(14,9,9,14,8,8,8),
     176            'Q' => array(6,9,9,9,13,11,6),
     177            'R' => array(14,9,9,14,12,10,9),
     178            'S' => array(6,9,8,6,1,9,6),
     179            'T' => array(14,4,4,4,4,4,4),
     180            'U' => array(9,9,9,9,9,9,6),
     181            'V' => array(0,0,0,10,10,10,4),
     182            'W' => array(8,8,8,8,10,13,8),// need to add \r
     183            'X' => array(9,9,6,6,6,9,9),
     184            //'Y' => array(9,9,9,9,6,6,6),
     185            'Y' => array(10,10,10,10,4,4,4),
     186            'Z' => array(15,1,2,6,4,8,15),
     187// russian cp1251
     188            'À' => array(6,9,9,15,9,9,9),
     189            'Á' => array(14,8,8,14,9,9,14),
     190            'Â' => array(14,9,9,14,9,9,14),
     191            'Ã' => array(15,8,8,8,8,8,8),
     192            'Ä' => array(14,9,9,9,9,9,14),
     193            'Å' => array(15,8,8,14,8,8,15),
     194            'š' => array(6,15,8,14,8,8,15),
     195            //Æ is combine: >\n<
     196            'Ç' => array(6,9,1,2,1,9,6),
     197            'È' => array(9,9,9,11,13,9,9),
     198            'É' => array(13,9,9,11,13,9,9),
     199            'Ê' => array(9,10,12,10,9,9,9),
     200            'Ë' => array(7,9,9,9,9,9,9),
     201            'Ì' => array(8,13,10,8,8,8,8),// need to add \r
     202            'Í' => array(9,9,9,15,9,9,9),
     203            'Î' => array(6,9,9,9,9,9,6),
     204            'Ï' => array(15,9,9,9,9,9,9),
     205            'Ð' => array(14,9,9,14,8,8,8),
     206            'Ñ' => array(6,9,8,8,8,9,6),
     207            'Ò' => array(14,4,4,4,4,4,4),
     208            'Ó' => array(9,9,9,7,1,9,6),
     209            'Ô' => array(2,7,10,10,7,2,2),// need to add ¡
     210            'Õ' => array(9,9,6,6,6,9,9),
     211            'Ö' => array(10,10,10,10,10,15,1),
     212            '×' => array(9,9,9,7,1,1,1),
     213            'Ø' => array(10,10,10,10,10,10,15),// \r
     214            'Ù' => array(10,10,10,10,10,15,0),// need to add \r
     215            'Ú' => array(12,4,4,6,5,5,6),
     216            'Û' => array(8,8,8,14,9,9,14),// need to add |
     217            'Ü' => array(8,8,8,14,9,9,14),
     218            'Ý' => array(6,9,1,7,1,9,6),
     219            'Þ' => array(2,2,2,3,2,2,2),// need to add O
     220            'ß' => array(7,9,9,7,3,5,9)
     221            ),
     222
     223        $iSuperSampling = 3, $iMarg = 1, $iRad = 4;
     224         
     225    function DigitalLED74($aRadius = 2, $aMargin= 0.6) {
     226        $this->iRad = $aRadius;
     227        $this->iMarg = $aMargin;
    212228    }
    213 
    214     function SetSupersampling($aSuperSampling = 2) {
    215         $this->iSuperSampling = $aSuperSampling;
     229   
     230    function SetSupersampling($aSuperSampling = 2)      {
     231        $this->iSuperSampling = $aSuperSampling;
    216232    }
    217233
    218     function _GetLED($aLedIdx, $aColor = 0) {
    219         $width=  $this->iLED_X*$this->iRad*2 +  ($this->iLED_X+1)*$this->iMarg + $this->iRad ;
    220         $height= $this->iLED_Y*$this->iRad*2 +  ($this->iLED_Y)*$this->iMarg + $this->iRad * 2;
    221 
    222         // Adjust radious for supersampling
    223         $rad = $this->iRad * $this->iSuperSampling;
    224 
    225         // Margin in between "Led" dots
    226         $marg = $this->iMarg * $this->iSuperSampling;
    227 
    228         $swidth = $width*$this->iSuperSampling;
    229         $sheight = $height*$this->iSuperSampling;
    230 
    231         $simg = new RotImage($swidth, $sheight, 0, DEFAULT_GFORMAT, false);
    232         $simg->SetColor($this->iColorSchema[$aColor][2]);
    233         $simg->FilledRectangle(0, 0, $swidth-1, $sheight-1);
    234 
    235         if( array_key_exists($aLedIdx, $this->iLEDSpec) ) {
    236             $d = $this->iLEDSpec[$aLedIdx];
    237         }
    238         else {
    239             $d = array(0,0,0,0,0,0,0);
    240         }
    241 
    242         for($r = 0; $r < 7; ++$r) {
    243             $dr = $d[$r];
    244             for($c = 0; $c < 4; ++$c) {
    245                 if( ($dr & pow(2,3-$c)) !== 0 ) {
    246                     $color = $this->iColorSchema[$aColor][0];
    247                 }
    248                 else {
    249                     $color = $this->iColorSchema[$aColor][1];
    250                 }
    251 
    252                 $x = 2*$rad*$c+$rad + ($c+1)*$marg + $rad ;
    253                 $y = 2*$rad*$r+$rad + ($r+1)*$marg + $rad ;
    254 
    255                 $simg->SetColor($color);
    256                 $simg->FilledCircle($x,$y,$rad);
    257             }
    258         }
    259 
    260         $img =  new Image($width, $height, DEFAULT_GFORMAT, false);
    261         $img->Copy($simg->img, 0, 0, 0, 0, $width, $height, $swidth, $sheight);
    262         $simg->Destroy();
    263         unset($simg);
    264         return $img;
     234    function _GetLED($aLedIdx, $aColor = 0)     {
     235        $width=  $this->iLED_X*$this->iRad*2 +  ($this->iLED_X+1)*$this->iMarg + $this->iRad ;
     236        $height= $this->iLED_Y*$this->iRad*2 +  ($this->iLED_Y)*$this->iMarg + $this->iRad * 2;
     237
     238        // Adjust radious for supersampling
     239        $rad = $this->iRad * $this->iSuperSampling;
     240
     241        // Margin in between "Led" dots
     242        $marg = $this->iMarg * $this->iSuperSampling;
     243       
     244        $swidth = $width*$this->iSuperSampling;
     245        $sheight = $height*$this->iSuperSampling;
     246
     247        $simg = new RotImage($swidth, $sheight, 0, DEFAULT_GFORMAT, false);
     248        $simg->SetColor($this->iColorSchema[$aColor][2]);
     249        $simg->FilledRectangle(0, 0, $swidth-1, $sheight-1);
     250
     251        if(array_key_exists($aLedIdx, $this->iLEDSpec)) {
     252            $d = $this->iLEDSpec[$aLedIdx];
     253        }
     254        else {
     255            $d = array(0,0,0,0,0,0,0);
     256        }
     257
     258        for($r = 0; $r < 7; ++$r) {
     259            $dr = $d[$r];
     260            for($c = 0; $c < 4; ++$c) {
     261                if( ($dr & pow(2,3-$c)) !== 0 ) {
     262                    $color = $this->iColorSchema[$aColor][0];
     263                }
     264                else {
     265                    $color = $this->iColorSchema[$aColor][1];
     266                }
     267
     268                $x = 2*$rad*$c+$rad + ($c+1)*$marg + $rad ;
     269                $y = 2*$rad*$r+$rad + ($r+1)*$marg + $rad ;
     270
     271                $simg->SetColor($color);
     272                $simg->FilledCircle($x,$y,$rad);
     273            }
     274        }
     275
     276        $img =  new Image($width, $height, DEFAULT_GFORMAT, false);
     277        $img->Copy($simg->img, 0, 0, 0, 0, $width, $height, $swidth, $sheight);
     278        $simg->Destroy();
     279        unset($simg);
     280        return $img;
    265281    }
    266282
    267 
    268     function Stroke($aValStr, $aColor = 0, $aFileName = '') {
    269         $this->StrokeNumber($aValStr, $aColor, $aFileName);
    270     }
    271 
    272 
    273283    function StrokeNumber($aValStr, $aColor = 0, $aFileName = '') {
    274         if( $aColor < 0 || $aColor >= sizeof($this->iColorSchema) ) {
    275             $aColor = 0;
    276         }
    277 
    278         if(($n = mb_strlen($aValStr,'utf8')) == 0) {
    279             $aValStr = ' ';
    280             $n = 1;
    281         }
    282 
    283         for($i = 0; $i < $n; ++$i) {
    284             $d = mb_substr($aValStr, $i, 1, 'utf8');
    285             if(  ctype_digit($d) ) {
    286                 $d = (int)$d;
    287             }
    288             else {
    289                $d = strtoupper($d);
    290             }
    291             $digit_img[$i] = $this->_GetLED($d, $aColor);
    292         }
    293 
    294         $w = imagesx($digit_img[0]->img);
    295         $h = imagesy($digit_img[0]->img);
    296 
    297         $number_img = new Image($w*$n, $h, DEFAULT_GFORMAT, false);
    298 
    299         for($i = 0; $i < $n; ++$i) {
    300             $number_img->Copy($digit_img[$i]->img, $i*$w, 0, 0, 0, $w, $h, $w, $h);
    301         }
    302 
    303         if( $aFileName != '' ) {
    304             $number_img->Stream($aFileName);
    305         } else {
    306             $number_img->Headers();
    307             $number_img->Stream();
    308         }
     284        if($aColor < 0 || $aColor >= sizeof($this->iColorSchema))
     285            $aColor = 0;
     286
     287        if(($n = strlen($aValStr)) == 0) {
     288            $aValStr = ' ';
     289            $n = 1;
     290        }
     291
     292        for($i = 0; $i < $n; ++$i) {
     293            $d = substr($aValStr, $i, 1);
     294            if(  $d >= '0' && $d <= '9' ) {
     295                $d = (int)$d;
     296            }
     297            else {
     298                $d = strtoupper($d);
     299            }
     300            $digit_img[$i] = $this->_GetLED($d, $aColor);
     301        }
     302
     303        $w = imagesx($digit_img[0]->img);
     304        $h = imagesy($digit_img[0]->img);
     305
     306        $number_img = new Image($w*$n, $h, DEFAULT_GFORMAT, false);
     307
     308        for($i = 0; $i < $n; ++$i) {
     309            $number_img->Copy($digit_img[$i]->img, $i*$w, 0, 0, 0, $w, $h, $w, $h);
     310        }
     311
     312        if( $aFileName != '' ) {
     313            $number_img->Stream($aFileName);
     314        } else {
     315            $number_img->Headers();
     316            $number_img->Stream();
     317        }
    309318    }
    310319}
  • trunk/client/modules/Elezioni/grafici/jpgraph_legend.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_LEGEND.INC.PHP
    4 // Description: Class to handle the legend box in the graph that gives
    5 //              names on the data series. The number of rows and columns
    6 //              in the legend are user specifyable.
    7 // Created:     2001-01-08 (Refactored to separate file 2008-08-01)
    8 // Ver:         $Id: jpgraph_legend.inc.php 1926 2010-01-11 16:33:07Z ljp $
     3// File:        JPGRAPH_LEGEND.INC.PHP
     4// Description: Class to handle the legend box in the graph that gives
     5//              names on the data series. The number of rows and columns
     6//              in the legend are user specifyable.
     7// Created:     2001-01-08 (Refactored to separate file 2008-08-01)
     8// Ver:         $Id: jpgraph_legend.inc.php 1048 2008-08-01 19:56:46Z ljp $
    99//
    10 // Copyright (c) Asial Corporation. All rights reserved.
     10// Copyright (c) Aditus Consulting. All rights reserved.
    1111//========================================================================
    1212
    1313DEFINE('_DEFAULT_LPM_SIZE',8); // Default Legend Plot Mark size
    1414
    15 
     15       
    1616//===================================================
    1717// CLASS Legend
     
    2222class Legend {
    2323    public $txtcol=array();
    24     public $font_family=FF_DEFAULT,$font_style=FS_NORMAL,$font_size=8; // old. 12
    25     private $color=array(120,120,120); // Default frame color
    26     private $fill_color=array(245,245,245); // Default fill color
    27     private $shadow=false; // Shadow around legend "box"
    28     private $shadow_color='darkgray';
     24    private $color=array(0,0,0); // Default fram color
     25    private $fill_color=array(235,235,235); // Default fill color
     26    private $shadow=true; // Shadow around legend "box"
     27    private $shadow_color='darkgray@0.5';
    2928    private $mark_abs_hsize=_DEFAULT_LPM_SIZE,$mark_abs_vsize=_DEFAULT_LPM_SIZE;
    30     private $xmargin=10,$ymargin=0,$shadow_width=2;
    31     private $xlmargin=4;
    32     private $ylinespacing=5;
    33    
    34      // We need a separate margin since the baseline of the last text would coincide with the bottom otherwise
    35     private $ybottom_margin = 8;
    36    
     29    private $xmargin=10,$ymargin=3,$shadow_width=2;
     30    private $xlmargin=2, $ylmargin='';
    3731    private $xpos=0.05, $ypos=0.15, $xabspos=-1, $yabspos=-1;
    3832    private $halign="right", $valign="top";
     33    private $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12;
    3934    private $font_color='black';
    4035    private $hide=false,$layout_n=1;
     
    4237    private $csimareas='';
    4338    private $reverse = false ;
    44     private $bkg_gradtype=-1, $bkg_gradfrom='lightgray', $bkg_gradto='gray';
    45 
    46     //---------------
    47     // CONSTRUCTOR
    48     function __construct() {
    49         // Empty
    50     }
    51     //---------------
    52     // PUBLIC METHODS
     39
     40//---------------
     41// CONSTRUCTOR
     42    function Legend() {
     43        // Empty
     44    }
     45//---------------
     46// PUBLIC METHODS       
    5347    function Hide($aHide=true) {
    54         $this->hide=$aHide;
    55     }
    56 
     48        $this->hide=$aHide;
     49    }
     50       
    5751    function SetHColMargin($aXMarg) {
    58         $this->xmargin = $aXMarg;
     52        $this->xmargin = $aXMarg;
    5953    }
    6054
    6155    function SetVColMargin($aSpacing) {
    62         $this->ylinespacing = $aSpacing ;
     56        $this->ymargin = $aSpacing ;
    6357    }
    6458
    6559    function SetLeftMargin($aXMarg) {
    66         $this->xlmargin = $aXMarg;
     60        $this->xlmargin = $aXMarg;
    6761    }
    6862
    6963    // Synonym
    7064    function SetLineSpacing($aSpacing) {
    71         $this->ylinespacing = $aSpacing ;
    72     }
    73 
    74     function SetShadow($aShow='gray',$aWidth=4) {
    75         if( is_string($aShow) ) {
    76             $this->shadow_color = $aShow;
    77             $this->shadow=true;
    78         }
    79         else {
    80             $this->shadow = $aShow;
    81         }
    82         $this->shadow_width = $aWidth;
     65        $this->ymargin = $aSpacing ;
     66    }
     67
     68    function SetShadow($aShow='gray',$aWidth=2) {
     69        if( is_string($aShow) ) {
     70            $this->shadow_color = $aShow;
     71            $this->shadow=true;
     72        }
     73        else
     74            $this->shadow=$aShow;
     75        $this->shadow_width=$aWidth;
    8376    }
    8477
    8578    function SetMarkAbsSize($aSize) {
    86         $this->mark_abs_vsize = $aSize ;
    87         $this->mark_abs_hsize = $aSize ;
     79        $this->mark_abs_vsize = $aSize ;
     80        $this->mark_abs_hsize = $aSize ;
    8881    }
    8982
    9083    function SetMarkAbsVSize($aSize) {
    91         $this->mark_abs_vsize = $aSize ;
     84        $this->mark_abs_vsize = $aSize ;
    9285    }
    9386
    9487    function SetMarkAbsHSize($aSize) {
    95         $this->mark_abs_hsize = $aSize ;
     88        $this->mark_abs_hsize = $aSize ;
    9689    }
    9790
    9891    function SetLineWeight($aWeight) {
    99         $this->weight = $aWeight;
     92        $this->weight = $aWeight;
    10093    }
    10194
    10295    function SetFrameWeight($aWeight) {
    103         $this->frameweight = $aWeight;
    104     }
    105 
     96        $this->frameweight = $aWeight;
     97    }
     98       
    10699    function SetLayout($aDirection=LEGEND_VERT) {
    107         $this->layout_n = $aDirection==LEGEND_VERT ? 1 : 99 ;
    108     }
    109 
     100        $this->layout_n = $aDirection==LEGEND_VERT ? 1 : 99 ;
     101    }
     102       
    110103    function SetColumns($aCols) {
    111         $this->layout_n = $aCols ;
     104        $this->layout_n = $aCols ;
    112105    }
    113106
    114107    function SetReverse($f=true) {
    115         $this->reverse = $f ;
     108        $this->reverse = $f ;
    116109    }
    117110
    118111    // Set color on frame around box
    119112    function SetColor($aFontColor,$aColor='black') {
    120         $this->font_color=$aFontColor;
    121         $this->color=$aColor;
    122     }
    123 
     113        $this->font_color=$aFontColor;
     114        $this->color=$aColor;
     115    }
     116       
    124117    function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) {
    125         $this->font_family = $aFamily;
    126         $this->font_style = $aStyle;
    127         $this->font_size = $aSize;
    128     }
    129 
    130     function SetPos($aX,$aY,$aHAlign='right',$aVAlign='top') {
    131         $this->Pos($aX,$aY,$aHAlign,$aVAlign);
    132     }
    133 
    134     function SetAbsPos($aX,$aY,$aHAlign='right',$aVAlign='top') {
    135         $this->xabspos=$aX;
    136         $this->yabspos=$aY;
    137         $this->halign=$aHAlign;
    138         $this->valign=$aVAlign;
    139     }
    140 
    141     function Pos($aX,$aY,$aHAlign='right',$aVAlign='top') {
    142         if( !($aX<1 && $aY<1) ) {
    143             JpGraphError::RaiseL(25120);//(" Position for legend must be given as percentage in range 0-1");
    144         }
    145         $this->xpos=$aX;
    146         $this->ypos=$aY;
    147         $this->halign=$aHAlign;
    148         $this->valign=$aVAlign;
     118        $this->font_family = $aFamily;
     119        $this->font_style = $aStyle;
     120        $this->font_size = $aSize;
     121    }
     122       
     123    function SetPos($aX,$aY,$aHAlign="right",$aVAlign="top") {
     124        $this->Pos($aX,$aY,$aHAlign,$aVAlign);
     125    }
     126
     127    function SetAbsPos($aX,$aY,$aHAlign="right",$aVAlign="top") {
     128        $this->xabspos=$aX;
     129        $this->yabspos=$aY;
     130        $this->halign=$aHAlign;
     131        $this->valign=$aVAlign;
     132    }
     133
     134
     135    function Pos($aX,$aY,$aHAlign="right",$aVAlign="top") {
     136        if( !($aX<1 && $aY<1) )
     137            JpGraphError::RaiseL(25120);//(" Position for legend must be given as percentage in range 0-1");
     138        $this->xpos=$aX;
     139        $this->ypos=$aY;
     140        $this->halign=$aHAlign;
     141        $this->valign=$aVAlign;
    149142    }
    150143
    151144    function SetFillColor($aColor) {
    152         $this->fill_color=$aColor;
    153     }
    154 
    155     function Clear() {
    156         $this->txtcol = array();
    157     }
    158 
     145        $this->fill_color=$aColor;
     146    }
     147       
    159148    function Add($aTxt,$aColor,$aPlotmark='',$aLinestyle=0,$csimtarget='',$csimalt='',$csimwintarget='') {
    160         $this->txtcol[]=array($aTxt,$aColor,$aPlotmark,$aLinestyle,$csimtarget,$csimalt,$csimwintarget);
     149        $this->txtcol[]=array($aTxt,$aColor,$aPlotmark,$aLinestyle,$csimtarget,$csimalt,$csimwintarget);
    161150    }
    162151
    163152    function GetCSIMAreas() {
    164         return $this->csimareas;
    165     }
    166 
    167     function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2) {
    168         $this->bkg_gradtype=$aGradType;
    169         $this->bkg_gradfrom = $aFrom;
    170         $this->bkg_gradto = $aTo;
    171     }
    172 
    173     function HasItems() {
    174         return (boolean)(count($this->txtcol));
    175     }
    176 
    177     function Stroke($aImg) {
    178         // Constant
    179         $fillBoxFrameWeight=1;
    180 
    181         if( $this->hide ) return;
    182 
    183         $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
    184 
    185         if( $this->reverse ) {
    186             $this->txtcol = array_reverse($this->txtcol);
    187         }
    188 
    189         $n=count($this->txtcol);
    190         if( $n == 0 ) return;
    191 
    192         // Find out the max width and height of each column to be able
     153        return $this->csimareas;
     154    }
     155       
     156    function Stroke(&$aImg) {
     157        // Constant
     158        $fillBoxFrameWeight=1;
     159
     160        if( $this->hide ) return;
     161
     162        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);         
     163
     164        if( $this->reverse ) {
     165            $this->txtcol = array_reverse($this->txtcol);
     166        }
     167
     168        $n=count($this->txtcol);
     169        if( $n == 0 ) return;
     170
     171        // Find out the max width and height of each column to be able
    193172        // to size the legend box.
    194         $numcolumns = ($n > $this->layout_n ? $this->layout_n : $n);
    195         for( $i=0; $i < $numcolumns; ++$i ) {
    196             $colwidth[$i] = $aImg->GetTextWidth($this->txtcol[$i][0]) +
    197                             2*$this->xmargin + 2*$this->mark_abs_hsize;
    198             $colheight[$i] = 0;
    199 
    200         }
    201 
    202         // Find our maximum height in each row
    203         $rows = 0 ; $rowheight[0] = 0;
    204         for( $i=0; $i < $n; ++$i ) {
    205             $h = max($this->mark_abs_vsize,$aImg->GetTextHeight($this->txtcol[$i][0]))+$this->ylinespacing;
    206 
    207             // Makes sure we always have a minimum of 1/4 (1/2 on each side) of the mark as space
    208             // between two vertical legend entries
    209             //$h = round(max($h,$this->mark_abs_vsize+$this->ymargin));
    210             //echo "Textheight #$i: tetxheight=".$aImg->GetTextHeight($this->txtcol[$i][0]).', ';
    211             //echo "h=$h ({$this->mark_abs_vsize},{$this->ymargin})<br>";
    212             if( $i % $numcolumns == 0 ) {
    213                 $rows++;
    214                 $rowheight[$rows-1] = 0;
    215             }
    216             $rowheight[$rows-1] = max($rowheight[$rows-1],$h)+1;
    217         }
    218 
    219         $abs_height = 0;
    220         for( $i=0; $i < $rows; ++$i ) {
    221             $abs_height += $rowheight[$i] ;
    222         }
    223 
    224         // Make sure that the height is at least as high as mark size + ymargin
    225         $abs_height = max($abs_height,$this->mark_abs_vsize);
    226         $abs_height += $this->ybottom_margin;
    227 
    228         // Find out the maximum width in each column
    229         for( $i=$numcolumns; $i < $n; ++$i ) {
    230             $colwidth[$i % $numcolumns] = max(
    231                 $aImg->GetTextWidth($this->txtcol[$i][0])+2*$this->xmargin+2*$this->mark_abs_hsize,
    232                 $colwidth[$i % $numcolumns]);
    233         }
    234 
    235         // Get the total width
    236         $mtw = 0;
    237         for( $i=0; $i < $numcolumns; ++$i ) {
    238             $mtw += $colwidth[$i] ;
    239         }
    240 
    241         // remove the last rows interpace margin (since there is no next row)
    242         $abs_height -= $this->ylinespacing;
    243 
    244 
    245         // Find out maximum width we need for legend box
    246         $abs_width = $mtw+$this->xlmargin+($numcolumns-1)*$this->mark_abs_hsize;
    247 
    248         if( $this->xabspos === -1  && $this->yabspos === -1 ) {
    249             $this->xabspos = $this->xpos*$aImg->width ;
    250             $this->yabspos = $this->ypos*$aImg->height ;
    251         }
    252 
    253         // Positioning of the legend box
    254         if( $this->halign == 'left' ) {
    255                 $xp = $this->xabspos;
    256         }
    257         elseif( $this->halign == 'center' ) {
    258                 $xp = $this->xabspos - $abs_width/2;
    259         }
    260         else {
    261                 $xp = $aImg->width - $this->xabspos - $abs_width;
    262         }
    263 
    264         $yp=$this->yabspos;
    265         if( $this->valign == 'center' ) {
    266                 $yp-=$abs_height/2;
    267         }
    268         elseif( $this->valign == 'bottom' ) {
    269                 $yp-=$abs_height;
    270         }
    271 
    272         // Stroke legend box
    273         $aImg->SetColor($this->color);
    274         $aImg->SetLineWeight($this->frameweight);
    275         $aImg->SetLineStyle('solid');
    276 
    277         if( $this->shadow ) {
    278                 $aImg->ShadowRectangle($xp,$yp,
    279                                    $xp+$abs_width+$this->shadow_width+2,
    280                                    $yp+$abs_height+$this->shadow_width+2,
    281                                    $this->fill_color,$this->shadow_width+2,$this->shadow_color);
    282         }
    283         else {
    284             $aImg->SetColor($this->fill_color);
    285             $aImg->FilledRectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height);
    286             $aImg->SetColor($this->color);
    287             $aImg->Rectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height);
    288         }
    289 
    290         if( $this->bkg_gradtype >= 0 ) {
    291             $grad = new Gradient($aImg);
    292             $grad->FilledRectangle($xp+1, $yp+1,
    293                                    $xp+$abs_width-3, $yp+$abs_height-3,
    294                                    $this->bkg_gradfrom, $this->bkg_gradto,
    295                                    $this->bkg_gradtype);
    296         }
    297 
    298         // x1,y1 is the position for the legend marker + text
    299         // The vertical position is the baseline position for the text
    300         // and every marker is adjusted acording to that.
    301 
    302         // For multiline texts this get more complicated.
    303 
    304         $x1 = $xp + $this->xlmargin;
    305         $y1 = $yp + $rowheight[0] - $this->ylinespacing + 2 ; // The ymargin is included in rowheight
    306 
    307         // Now, y1 is the bottom vertical position of the first legend, i.e if
    308         // the legend has multiple lines it is the bottom line.
    309 
    310         $grad = new Gradient($aImg);
    311         $patternFactory = null;
    312 
    313         // Now stroke each legend in turn
    314         // Each plot has added the following information to  the legend
    315         // p[0] = Legend text
    316         // p[1] = Color,
    317         // p[2] = For markers a reference to the PlotMark object
    318         // p[3] = For lines the line style, for gradient the negative gradient style
    319         // p[4] = CSIM target
    320         // p[5] = CSIM Alt text
    321         $i = 1 ; $row = 0;
    322         foreach($this->txtcol as $p) {
    323 
    324             // STROKE DEBUG BOX
    325             if( _JPG_DEBUG ) {
    326                 $aImg->SetLineWeight(1);
    327                 $aImg->SetColor('red');
    328                 $aImg->SetLineStyle('solid');
    329                 $aImg->Rectangle($x1,$y1,$xp+$abs_width-1,$y1-$rowheight[$row]);
    330             }
    331 
    332             $aImg->SetLineWeight($this->weight);
    333             $x1 = round($x1)+1; // We add one to not collide with the border
    334             $y1=round($y1);
    335 
    336             // This is the center offset up from the baseline which is
    337             // considered the "center" of the marks. This gets slightly complicated since
    338             // we need to consider if the text is a multiline paragraph or if it is only
    339             // a single line. The reason is that for single line the y1 corresponds to the baseline
    340             // and that is fine. However for a multiline paragraph there is no single baseline
    341             // and in that case the y1 corresponds to the lowest y for the bounding box. In that
    342             // case we center the mark in the middle of the paragraph
    343             if( !preg_match('/\n/',$p[0]) ) {
    344                 // Single line
    345                 $marky = ceil($y1-$this->mark_abs_vsize/2)-1;
    346             } else {
    347                 // Paragraph
    348                 $marky = $y1 - $aImg->GetTextHeight($p[0])/2;
    349 
    350               //  echo "y1=$y1, p[o]={$p[0]}, marky=$marky<br>";
    351             }
    352 
    353             //echo "<br>Mark #$i: marky=$marky<br>";
    354 
    355             $x1 += $this->mark_abs_hsize;
    356    
    357             if ( !empty($p[2]) && $p[2]->GetType() > -1 ) {
    358 
    359 
    360                 // Make a plot mark legend. This is constructed with a mark which
    361                 // is run through with a line
    362 
    363                 // First construct a bit of the line that looks exactly like the
    364                 // line in the plot
    365                 $aImg->SetColor($p[1]);
    366                 if( is_string($p[3]) || $p[3]>0 ) {
    367                     $aImg->SetLineStyle($p[3]);
    368                     $aImg->StyleLine($x1-$this->mark_abs_hsize,$marky,$x1+$this->mark_abs_hsize,$marky);
    369                 }
    370 
    371                 // Stroke a mark using image
    372                 if( $p[2]->GetType() == MARK_IMG ) {
    373                     $p[2]->Stroke($aImg,$x1,$marky);
    374                 }
    375 
    376                 // Stroke a mark with the standard size
    377                 // (As long as it is not an image mark )
    378                 if( $p[2]->GetType() != MARK_IMG ) {
    379 
    380                     // Clear any user callbacks since we ont want them called for
    381                     // the legend marks
    382                     $p[2]->iFormatCallback = '';
    383                     $p[2]->iFormatCallback2 = '';
    384 
    385                     // Since size for circles is specified as the radius
    386                     // this means that we must half the size to make the total
    387                     // width behave as the other marks
    388                     if( $p[2]->GetType() == MARK_FILLEDCIRCLE || $p[2]->GetType() == MARK_CIRCLE ) {
    389                         $p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize)/2);
    390                         $p[2]->Stroke($aImg,$x1,$marky);
    391                     }
    392                     else {
    393                         $p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize));
    394                         $p[2]->Stroke($aImg,$x1,$marky);
    395                     }
    396                 }
    397             }
    398             elseif ( !empty($p[2]) && (is_string($p[3]) || $p[3]>0 ) ) {
    399                 // Draw a styled line
    400                 $aImg->SetColor($p[1]);
    401                 $aImg->SetLineStyle($p[3]);
    402                 $aImg->StyleLine($x1-$this->mark_abs_hsize,$marky,$x1+$this->mark_abs_hsize,$marky);
    403                 $aImg->StyleLine($x1-$this->mark_abs_hsize,$marky+1,$x1+$this->mark_abs_hsize,$marky+1);
    404             }
    405             else {
    406                 // Draw a colored box
    407                 $color = $p[1] ;
    408 
    409                 // We make boxes slightly larger to better show
    410                 $boxsize = max($this->mark_abs_vsize,$this->mark_abs_hsize) + 2 ;
    411 
    412                 $ym = $marky-ceil($boxsize/2) ; // Marker y-coordinate
    413 
    414                 // We either need to plot a gradient or a
    415                 // pattern. To differentiate we use a kludge.
    416                 // Patterns have a p[3] value of < -100
    417                 if( $p[3] < -100 ) {
    418                     // p[1][0] == iPattern, p[1][1] == iPatternColor, p[1][2] == iPatternDensity
    419                     if( $patternFactory == null ) {
    420                         $patternFactory = new RectPatternFactory();
    421                     }
    422                     $prect = $patternFactory->Create($p[1][0],$p[1][1],1);
    423                     $prect->SetBackground($p[1][3]);
    424                     $prect->SetDensity($p[1][2]+1);
    425                     $prect->SetPos(new Rectangle($x1,$ym,$boxsize,$boxsize));
    426                     $prect->Stroke($aImg);
    427                     $prect=null;
    428                 }
    429                 else {
    430                     if( is_array($color) && count($color)==2 ) {
    431                         // The client want a gradient color
    432                         $grad->FilledRectangle($x1-$boxsize/2,$ym,
    433                                                $x1+$boxsize/2,$ym+$boxsize,
    434                                                $color[0],$color[1],-$p[3]);
    435                     }
    436                     else {
    437                         $aImg->SetColor($p[1]);
    438                         $aImg->FilledRectangle($x1-$boxsize/2,$ym, $x1+$boxsize/2,$ym+$boxsize);
    439                     }
    440 
    441                     // Draw a plot frame line
    442                     $aImg->SetColor($this->color);
    443                     $aImg->SetLineWeight($fillBoxFrameWeight);
    444                     $aImg->Rectangle($x1-$boxsize/2,$ym,
    445                                      $x1+$boxsize/2,$ym+$boxsize);
    446                 }
    447             }
    448             $aImg->SetColor($this->font_color);
    449             $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
    450             $aImg->SetTextAlign('left','baseline');
    451 
    452             $debug=false;
    453             $aImg->StrokeText($x1+$this->mark_abs_hsize+$this->xmargin,$y1,$p[0],
    454                 0,'left',$debug);
    455 
    456             // Add CSIM for Legend if defined
    457             if( !empty($p[4]) ) {
    458 
    459                 $xs = $x1 - $this->mark_abs_hsize ;
    460                 $ys = $y1 + 1 ;
    461                 $xe = $x1 + $aImg->GetTextWidth($p[0]) + $this->mark_abs_hsize + $this->xmargin ;
    462                 $ye = $y1-$rowheight[$row]+1;
    463                 $coords = "$xs,$ys,$xe,$y1,$xe,$ye,$xs,$ye";
    464                 if( ! empty($p[4]) ) {
    465                     $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($p[4])."\"";
    466 
    467                     if( !empty($p[6]) ) {
    468                         $this->csimareas .= " target=\"".$p[6]."\"";
    469                     }
    470 
    471                     if( !empty($p[5]) ) {
    472                         $tmp=sprintf($p[5],$p[0]);
    473                         $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
    474                     }
    475                     $this->csimareas .= " />\n";
    476                 }
    477             }
    478 
    479             if( $i >= $this->layout_n ) {
    480                 $x1 = $xp+$this->xlmargin;
    481                 $row++;
    482                 if( !empty($rowheight[$row]) )
    483                     $y1 += $rowheight[$row];
    484                 $i = 1;
    485             }
    486             else {
    487                 $x1 += $colwidth[($i-1) % $numcolumns] ;
    488                 ++$i;
    489             }
    490         }
     173        $numcolumns = ($n > $this->layout_n ? $this->layout_n : $n);
     174        for( $i=0; $i < $numcolumns; ++$i ) {
     175            $colwidth[$i] = $aImg->GetTextWidth($this->txtcol[$i][0]) +
     176                            2*$this->xmargin + 2*$this->mark_abs_hsize;
     177            $colheight[$i] = 0;
     178        }
     179
     180        // Find our maximum height in each row
     181        $rows = 0 ; $rowheight[0] = 0;
     182        for( $i=0; $i < $n; ++$i ) {
     183            $h = max($this->mark_abs_vsize,$aImg->GetTextHeight($this->txtcol[$i][0]))+$this->ymargin;
     184            if( $i % $numcolumns == 0 ) {
     185                $rows++;
     186                $rowheight[$rows-1] = 0;
     187            }
     188            $rowheight[$rows-1] = max($rowheight[$rows-1],$h);
     189        }
     190
     191        $abs_height = 0;
     192        for( $i=0; $i < $rows; ++$i ) {
     193            $abs_height += $rowheight[$i] ;
     194        }
     195
     196        // Make sure that the height is at least as high as mark size + ymargin
     197        $abs_height = max($abs_height,$this->mark_abs_vsize);
     198
     199        // We add 3 extra pixels height to compensate for the difficult in
     200        // calculating font height
     201        $abs_height += $this->ymargin+3;
     202                                               
     203        // Find out the maximum width in each column
     204        for( $i=$numcolumns; $i < $n; ++$i ) {
     205            $colwidth[$i % $numcolumns] = max(
     206                $aImg->GetTextWidth($this->txtcol[$i][0])+2*$this->xmargin+2*$this->mark_abs_hsize,$colwidth[$i % $numcolumns]);
     207        }
     208
     209        // Get the total width
     210        $mtw = 0;
     211        for( $i=0; $i < $numcolumns; ++$i ) {
     212            $mtw += $colwidth[$i] ;
     213        }
     214
     215        // Find out maximum width we need for legend box
     216        $abs_width = $mtw+$this->xlmargin;
     217
     218        if( $this->xabspos === -1  && $this->yabspos === -1 ) {
     219            $this->xabspos = $this->xpos*$aImg->width ;
     220            $this->yabspos = $this->ypos*$aImg->height ;
     221        }
     222
     223        // Positioning of the legend box
     224        if( $this->halign == 'left' )
     225            $xp = $this->xabspos;
     226        elseif( $this->halign == 'center' )
     227            $xp = $this->xabspos - $abs_width/2;
     228        else 
     229            $xp = $aImg->width - $this->xabspos - $abs_width;
     230
     231        $yp=$this->yabspos;
     232        if( $this->valign == 'center' )
     233            $yp-=$abs_height/2;
     234        elseif( $this->valign == 'bottom' )
     235            $yp-=$abs_height;
     236                       
     237        // Stroke legend box
     238        $aImg->SetColor($this->color); 
     239        $aImg->SetLineWeight($this->frameweight);
     240        $aImg->SetLineStyle('solid');
     241
     242        if( $this->shadow )
     243            $aImg->ShadowRectangle($xp,$yp,$xp+$abs_width+$this->shadow_width,
     244                                   $yp+$abs_height+$this->shadow_width,
     245                                   $this->fill_color,$this->shadow_width,$this->shadow_color);
     246        else {
     247            $aImg->SetColor($this->fill_color);                         
     248            $aImg->FilledRectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height);
     249            $aImg->SetColor($this->color);                                                     
     250            $aImg->Rectangle($xp,$yp,$xp+$abs_width,$yp+$abs_height);
     251        }
     252
     253        // x1,y1 is the position for the legend mark
     254        $x1=$xp+$this->mark_abs_hsize+$this->xlmargin;
     255        $y1=$yp + $this->ymargin;               
     256       
     257        $f2 =  round($aImg->GetTextHeight('X')/2);
     258
     259        $grad = new Gradient($aImg);
     260        $patternFactory = null;
     261
     262        // Now stroke each legend in turn
     263        // Each plot has added the following information to  the legend
     264        // p[0] = Legend text
     265        // p[1] = Color,
     266        // p[2] = For markers a reference to the PlotMark object
     267        // p[3] = For lines the line style, for gradient the negative gradient style
     268        // p[4] = CSIM target
     269        // p[5] = CSIM Alt text
     270        $i = 1 ; $row = 0;
     271        foreach($this->txtcol as $p) {
     272         
     273            // STROKE DEBUG BOX
     274            if( _JPG_DEBUG ) {
     275                $aImg->SetLineWeight(1);
     276                $aImg->SetColor('red');
     277                $aImg->SetLineStyle('solid');
     278                $aImg->Rectangle($xp,$y1,$xp+$abs_width,$y1+$rowheight[$row]);
     279            }
     280
     281            $aImg->SetLineWeight($this->weight);
     282            $x1 = round($x1); $y1=round($y1);
     283            if ( !empty($p[2]) && $p[2]->GetType() > -1 ) {
     284                // Make a plot mark legend
     285                $aImg->SetColor($p[1]);
     286                if( is_string($p[3]) || $p[3]>0 ) {
     287                    $aImg->SetLineStyle($p[3]);
     288                    $aImg->StyleLine($x1-$this->mark_abs_hsize,$y1+$f2,$x1+$this->mark_abs_hsize,$y1+$f2);
     289                }
     290                // Stroke a mark with the standard size
     291                // (As long as it is not an image mark )
     292                if( $p[2]->GetType() != MARK_IMG ) {
     293
     294                    // Clear any user callbacks since we ont want them called for
     295                    // the legend marks
     296                    $p[2]->iFormatCallback = '';
     297                    $p[2]->iFormatCallback2 = '';
     298
     299                    // Since size for circles is specified as the radius
     300                    // this means that we must half the size to make the total
     301                    // width behave as the other marks
     302                    if( $p[2]->GetType() == MARK_FILLEDCIRCLE || $p[2]->GetType() == MARK_CIRCLE ) {
     303                        $p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize)/2);
     304                        $p[2]->Stroke($aImg,$x1,$y1+$f2);
     305                    }
     306                    else {
     307                        $p[2]->SetSize(min($this->mark_abs_vsize,$this->mark_abs_hsize));
     308                        $p[2]->Stroke($aImg,$x1,$y1+$f2);
     309                    }
     310                }
     311            }
     312            elseif ( !empty($p[2]) && (is_string($p[3]) || $p[3]>0 ) ) {
     313                // Draw a styled line
     314                $aImg->SetColor($p[1]);
     315                $aImg->SetLineStyle($p[3]);
     316                $aImg->StyleLine($x1-1,$y1+$f2,$x1+$this->mark_abs_hsize,$y1+$f2);
     317                $aImg->StyleLine($x1-1,$y1+$f2+1,$x1+$this->mark_abs_hsize,$y1+$f2+1);
     318            }
     319            else {
     320                // Draw a colored box
     321                $color = $p[1] ;
     322                // We make boxes slightly larger to better show
     323                $boxsize = min($this->mark_abs_vsize,$this->mark_abs_hsize) + 2 ;
     324                $ym =  round($y1 + $f2 - $boxsize/2);
     325                // We either need to plot a gradient or a
     326                // pattern. To differentiate we use a kludge.
     327                // Patterns have a p[3] value of < -100
     328                if( $p[3] < -100 ) {
     329                    // p[1][0] == iPattern, p[1][1] == iPatternColor, p[1][2] == iPatternDensity
     330                    if( $patternFactory == null ) {
     331                        $patternFactory = new RectPatternFactory();
     332                    }               
     333                    $prect = $patternFactory->Create($p[1][0],$p[1][1],1);
     334                    $prect->SetBackground($p[1][3]);
     335                    $prect->SetDensity($p[1][2]+1);
     336                    $prect->SetPos(new Rectangle($x1,$ym,$boxsize,$boxsize));
     337                    $prect->Stroke($aImg);
     338                    $prect=null;
     339                }
     340                else {
     341                    if( is_array($color) && count($color)==2 ) {
     342                        // The client want a gradient color
     343                        $grad->FilledRectangle($x1,$ym,
     344                                               $x1+$boxsize,$ym+$boxsize,
     345                                               $color[0],$color[1],-$p[3]);
     346                    }
     347                    else {
     348                        $aImg->SetColor($p[1]);
     349                        $aImg->FilledRectangle($x1,$ym,$x1+$boxsize,$ym+$boxsize);
     350                    }
     351                    $aImg->SetColor($this->color);
     352                    $aImg->SetLineWeight($fillBoxFrameWeight);
     353                    $aImg->Rectangle($x1,$ym,$x1+$boxsize,$ym+$boxsize);
     354                }
     355            }
     356            $aImg->SetColor($this->font_color);
     357            $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);             
     358            $aImg->SetTextAlign("left","top");                 
     359            $aImg->StrokeText(round($x1+$this->mark_abs_hsize+$this->xmargin),$y1,$p[0]);
     360
     361            // Add CSIM for Legend if defined
     362            if( !empty($p[4]) ) {
     363               
     364                $xe = $x1 + $this->xmargin+$this->mark_abs_hsize+$aImg->GetTextWidth($p[0]);
     365                $ye = $y1 + max($this->mark_abs_vsize,$aImg->GetTextHeight($p[0]));
     366                $coords = "$x1,$y1,$xe,$y1,$xe,$ye,$x1,$ye";
     367                if( ! empty($p[4]) ) {
     368                    $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($p[4])."\"";
     369
     370                    if( !empty($p[6]) ) {
     371                        $this->csimareas .= " target=\"".$p[6]."\"";
     372                    }
     373
     374                    if( !empty($p[5]) ) {
     375                        $tmp=sprintf($p[5],$p[0]);
     376                        $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
     377                    }
     378                    $this->csimareas .= " />\n";
     379                }
     380            }
     381            if( $i >= $this->layout_n ) {
     382                $x1 = $xp+$this->mark_abs_hsize+$this->xlmargin;
     383                $y1 += $rowheight[$row++];
     384                $i = 1;
     385            }
     386            else {
     387                $x1 += $colwidth[($i-1) % $numcolumns] ;
     388                ++$i;
     389            }
     390        }       
    491391    }
    492392} // Class
    493 
     393       
    494394?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_line.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:                JPGRAPH_LINE.PHP
    4  // Description: Line plot extension for JpGraph
    5  // Created:     2001-01-08
    6  // Ver:                 $Id: jpgraph_line.php 1921 2009-12-11 11:46:39Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_LINE.PHP
     4// Description: Line plot extension for JpGraph
     5// Created:     2001-01-08
     6// Ver:         $Id: jpgraph_line.php 981 2008-03-24 11:51:12Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212require_once ('jpgraph_plotmark.inc.php');
     
    2020//===================================================
    2121// CLASS LinePlot
    22 // Description:
     22// Description: 
    2323//===================================================
    2424class LinePlot extends Plot{
     
    2727    protected $fill_color='blue';
    2828    protected $step_style=false, $center=false;
    29     protected $line_style=1; // Default to solid
     29    protected $line_style=1;    // Default to solid
    3030    protected $filledAreas = array(); // array of arrays(with min,max,col,filled in them)
    3131    public $barcenter=false;  // When we mix line and bar. Should we center the line in the bar.
    32     protected $fillFromMin = false, $fillFromMax = false;
     32    protected $fillFromMin = false ;
    3333    protected $fillgrad=false,$fillgrad_fromcolor='navy',$fillgrad_tocolor='silver',$fillgrad_numcolors=100;
    3434    protected $iFastStroke=false;
    3535
    36     //---------------
    37     // CONSTRUCTOR
    38     function __construct($datay,$datax=false) {
    39         parent::__construct($datay,$datax);
    40         $this->mark = new PlotMark() ;
    41         $this->color = ColorFactory::getColor();
    42         $this->fill_color = $this->color;
    43     }
    44     //---------------
    45     // PUBLIC METHODS
    46 
    47     function SetFilled($aFlg=true) {
    48                 $this->filled = $aFlg;
    49     }
    50 
     36//---------------
     37// CONSTRUCTOR
     38    function LinePlot($datay,$datax=false) {
     39        $this->Plot($datay,$datax);
     40        $this->mark = new PlotMark() ;
     41    }
     42//---------------
     43// PUBLIC METHODS       
     44
     45    // Set style, filled or open
     46    function SetFilled($aFlag=true) {
     47        JpGraphError::RaiseL(10001);//('LinePlot::SetFilled() is deprecated. Use SetFillColor()');
     48    }
     49       
    5150    function SetBarCenter($aFlag=true) {
    52         $this->barcenter=$aFlag;
     51        $this->barcenter=$aFlag;
    5352    }
    5453
    5554    function SetStyle($aStyle) {
    56         $this->line_style=$aStyle;
    57     }
    58 
     55        $this->line_style=$aStyle;
     56    }
     57       
    5958    function SetStepStyle($aFlag=true) {
    60         $this->step_style = $aFlag;
    61     }
    62 
     59        $this->step_style = $aFlag;
     60    }
     61       
    6362    function SetColor($aColor) {
    64         parent::SetColor($aColor);
    65     }
    66 
     63        parent::SetColor($aColor);
     64    }
     65       
    6766    function SetFillFromYMin($f=true) {
    68         $this->fillFromMin = $f ;
    69     }
    70 
    71     function SetFillFromYMax($f=true) {
    72         $this->fillFromMax = $f ;
    73     }
    74 
     67        $this->fillFromMin = $f ;
     68    }
     69   
    7570    function SetFillColor($aColor,$aFilled=true) {
    76         //$this->color = $aColor;
    77         $this->fill_color=$aColor;
    78         $this->filled=$aFilled;
     71        $this->fill_color=$aColor;
     72        $this->filled=$aFilled;
    7973    }
    8074
    8175    function SetFillGradient($aFromColor,$aToColor,$aNumColors=100,$aFilled=true) {
    82         $this->fillgrad_fromcolor = $aFromColor;
    83         $this->fillgrad_tocolor   = $aToColor;
    84         $this->fillgrad_numcolors = $aNumColors;
    85         $this->filled = $aFilled;
    86         $this->fillgrad = true;
    87     }
    88 
     76        $this->fillgrad_fromcolor = $aFromColor;
     77        $this->fillgrad_tocolor   = $aToColor;
     78        $this->fillgrad_numcolors = $aNumColors;
     79        $this->filled = $aFilled;
     80        $this->fillgrad = true;
     81    }
     82       
    8983    function Legend($graph) {
    90         if( $this->legend!="" ) {
    91             if( $this->filled && !$this->fillgrad ) {
    92                 $graph->legend->Add($this->legend,
    93                 $this->fill_color,$this->mark,0,
    94                 $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    95             }
    96             elseif( $this->fillgrad ) {
    97                 $color=array($this->fillgrad_fromcolor,$this->fillgrad_tocolor);
    98                 // In order to differentiate between gradients and cooors specified as an RGB triple
    99                 $graph->legend->Add($this->legend,$color,"",-2 /* -GRAD_HOR */,
    100                 $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    101             } else {
    102                 $graph->legend->Add($this->legend,
    103                 $this->color,$this->mark,$this->line_style,
    104                 $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    105             }
    106         }
     84        if( $this->legend!="" ) {
     85            if( $this->filled && !$this->fillgrad ) {
     86                $graph->legend->Add($this->legend,
     87                                    $this->fill_color,$this->mark,0,
     88                                    $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     89            }
     90            elseif( $this->fillgrad ) {
     91                $color=array($this->fillgrad_fromcolor,$this->fillgrad_tocolor);
     92                // In order to differentiate between gradients and cooors specified as an RGB triple
     93                $graph->legend->Add($this->legend,$color,"",-2 /* -GRAD_HOR */,
     94                                    $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     95            } else {
     96                $graph->legend->Add($this->legend,
     97                                    $this->color,$this->mark,$this->line_style,
     98                                    $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     99            }
     100        }       
    107101    }
    108102
    109103    function AddArea($aMin=0,$aMax=0,$aFilled=LP_AREA_NOT_FILLED,$aColor="gray9",$aBorder=LP_AREA_BORDER) {
    110         if($aMin > $aMax) {
    111             // swap
    112             $tmp = $aMin;
    113             $aMin = $aMax;
    114             $aMax = $tmp;
    115         }
    116         $this->filledAreas[] = array($aMin,$aMax,$aColor,$aFilled,$aBorder);
    117     }
    118 
     104        if($aMin > $aMax) {
     105            // swap
     106            $tmp = $aMin;
     107            $aMin = $aMax;
     108            $aMax = $tmp;
     109        }
     110        $this->filledAreas[] = array($aMin,$aMax,$aColor,$aFilled,$aBorder);
     111    }
     112       
    119113    // Gets called before any axis are stroked
    120114    function PreStrokeAdjust($graph) {
    121115
    122         // If another plot type have already adjusted the
    123         // offset we don't touch it.
    124         // (We check for empty in case the scale is  a log scale
    125         // and hence doesn't contain any xlabel_offset)
    126         if( empty($graph->xaxis->scale->ticks->xlabel_offset) || $graph->xaxis->scale->ticks->xlabel_offset == 0 ) {
    127             if( $this->center ) {
    128                 ++$this->numpoints;
    129                 $a=0.5; $b=0.5;
    130             } else {
    131                 $a=0; $b=0;
    132             }
    133             $graph->xaxis->scale->ticks->SetXLabelOffset($a);
    134             $graph->SetTextScaleOff($b);
    135             //$graph->xaxis->scale->ticks->SupressMinorTickMarks();
    136         }
    137     }
    138 
     116        // If another plot type have already adjusted the
     117        // offset we don't touch it.
     118        // (We check for empty in case the scale is  a log scale
     119        // and hence doesn't contain any xlabel_offset)
     120        if( empty($graph->xaxis->scale->ticks->xlabel_offset) ||
     121            $graph->xaxis->scale->ticks->xlabel_offset == 0 ) {
     122            if( $this->center ) {
     123                ++$this->numpoints;
     124                $a=0.5; $b=0.5;
     125            } else {
     126                $a=0; $b=0;
     127            }
     128            $graph->xaxis->scale->ticks->SetXLabelOffset($a);
     129            $graph->SetTextScaleOff($b);                                               
     130            //$graph->xaxis->scale->ticks->SupressMinorTickMarks();
     131        }
     132    }
     133   
    139134    function SetFastStroke($aFlg=true) {
    140         $this->iFastStroke = $aFlg;
     135        $this->iFastStroke = $aFlg;
    141136    }
    142137
    143138    function FastStroke($img,$xscale,$yscale,$aStartPoint=0,$exist_x=true) {
    144         // An optimized stroke for many data points with no extra
    145         // features but 60% faster. You can't have values or line styles, or null
    146         // values in plots.
    147         $numpoints=count($this->coords[0]);
    148         if( $this->barcenter ) {
    149             $textadj = 0.5-$xscale->text_scale_off;
    150         }
    151         else {
    152             $textadj = 0;
    153         }
    154 
    155         $img->SetColor($this->color);
    156         $img->SetLineWeight($this->weight);
    157         $pnts=$aStartPoint;
    158         while( $pnts < $numpoints ) {
    159             if( $exist_x ) {
    160                 $x=$this->coords[1][$pnts];
    161             }
    162             else {
    163                 $x=$pnts+$textadj;
    164             }
    165             $xt = $xscale->Translate($x);
    166             $y=$this->coords[0][$pnts];
    167             $yt = $yscale->Translate($y);
    168             if( is_numeric($y) ) {
    169                 $cord[] = $xt;
    170                 $cord[] = $yt;
    171             }
    172             elseif( $y == '-' && $pnts > 0 ) {
    173                 // Just ignore
    174             }
    175             else {
    176                 JpGraphError::RaiseL(10002);//('Plot too complicated for fast line Stroke. Use standard Stroke()');
    177             }
    178             ++$pnts;
    179         } // WHILE
    180 
    181         $img->Polygon($cord,false,true);
    182     }
    183 
     139        // An optimized stroke for many data points with no extra
     140        // features but 60% faster. You can't have values or line styles, or null
     141        // values in plots.
     142        $numpoints=count($this->coords[0]);
     143        if( $this->barcenter )
     144            $textadj = 0.5-$xscale->text_scale_off;
     145        else
     146            $textadj = 0;
     147
     148        $img->SetColor($this->color);
     149        $img->SetLineWeight($this->weight);
     150        $pnts=$aStartPoint;
     151        while( $pnts < $numpoints ) {       
     152            if( $exist_x ) $x=$this->coords[1][$pnts];
     153            else $x=$pnts+$textadj;
     154            $xt = $xscale->Translate($x);
     155            $y=$this->coords[0][$pnts];
     156            $yt = $yscale->Translate($y);   
     157            if( is_numeric($y) ) {
     158                $cord[] = $xt;
     159                $cord[] = $yt;
     160            }
     161            elseif( $y == '-' && $pnts > 0 ) {
     162                // Just ignore
     163            }
     164            else {
     165                JpGraphError::RaiseL(10002);//('Plot too complicated for fast line Stroke. Use standard Stroke()');
     166            }
     167            ++$pnts;
     168        } // WHILE
     169
     170        $img->Polygon($cord,false,true);
     171    }
     172       
    184173    function Stroke($img,$xscale,$yscale) {
    185         $idx=0;
    186         $numpoints=count($this->coords[0]);
    187         if( isset($this->coords[1]) ) {
    188             if( count($this->coords[1])!=$numpoints ) {
    189                 JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints);
    190             //("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints");
    191             }
    192             else {
    193                 $exist_x = true;
    194             }
    195         }
    196         else {
    197             $exist_x = false;
    198         }
    199 
    200         if( $this->barcenter ) {
    201             $textadj = 0.5-$xscale->text_scale_off;
    202         }
    203         else {
    204             $textadj = 0;
    205         }
    206 
    207         // Find the first numeric data point
    208         $startpoint=0;
    209         while( $startpoint < $numpoints && !is_numeric($this->coords[0][$startpoint]) ) {
    210             ++$startpoint;
    211         }
    212 
    213         // Bail out if no data points
    214         if( $startpoint == $numpoints ) return;
    215 
    216         if( $this->iFastStroke ) {
    217             $this->FastStroke($img,$xscale,$yscale,$startpoint,$exist_x);
    218             return;
    219         }
    220 
    221         if( $exist_x ) {
    222             $xs=$this->coords[1][$startpoint];
    223         }
    224         else {
    225             $xs= $textadj+$startpoint;
    226         }
    227 
    228         $img->SetStartPoint($xscale->Translate($xs),
    229         $yscale->Translate($this->coords[0][$startpoint]));
    230 
    231         if( $this->filled ) {
    232             if( $this->fillFromMax ) {
    233                 //$max = $yscale->GetMaxVal();
    234                 $cord[$idx++] = $xscale->Translate($xs);
    235                 $cord[$idx++] = $yscale->scale_abs[1];
    236             }
    237             else {
    238                 $min = $yscale->GetMinVal();
    239                 if( $min > 0 || $this->fillFromMin ) {
    240                     $fillmin = $yscale->scale_abs[0];//Translate($min);
    241                 }
    242                 else {
    243                     $fillmin = $yscale->Translate(0);
    244                 }
    245 
    246                 $cord[$idx++] = $xscale->Translate($xs);
    247                 $cord[$idx++] = $fillmin;
    248             }
    249         }
    250         $xt = $xscale->Translate($xs);
    251         $yt = $yscale->Translate($this->coords[0][$startpoint]);
    252         $cord[$idx++] = $xt;
    253         $cord[$idx++] = $yt;
    254         $yt_old = $yt;
    255         $xt_old = $xt;
    256         $y_old = $this->coords[0][$startpoint];
    257 
    258         $this->value->Stroke($img,$this->coords[0][$startpoint],$xt,$yt);
    259 
    260         $img->SetColor($this->color);
    261         $img->SetLineWeight($this->weight);
    262         $img->SetLineStyle($this->line_style);
    263         $pnts=$startpoint+1;
    264         $firstnonumeric = false;
    265 
    266 
    267         while( $pnts < $numpoints ) {
    268 
    269             if( $exist_x ) {
    270                 $x=$this->coords[1][$pnts];
    271             }
    272             else {
    273                 $x=$pnts+$textadj;
    274             }
    275             $xt = $xscale->Translate($x);
    276             $yt = $yscale->Translate($this->coords[0][$pnts]);
    277 
    278             $y=$this->coords[0][$pnts];
    279             if( $this->step_style ) {
    280                 // To handle null values within step style we need to record the
    281                 // first non numeric value so we know from where to start if the
    282                 // non value is '-'.
    283                 if( is_numeric($y) ) {
    284                     $firstnonumeric = false;
    285                     if( is_numeric($y_old) ) {
    286                         $img->StyleLine($xt_old,$yt_old,$xt,$yt_old);
    287                         $img->StyleLine($xt,$yt_old,$xt,$yt);
    288                     }
    289                     elseif( $y_old == '-' ) {
    290                         $img->StyleLine($xt_first,$yt_first,$xt,$yt_first);
    291                         $img->StyleLine($xt,$yt_first,$xt,$yt);
    292                     }
    293                     else {
    294                         $yt_old = $yt;
    295                         $xt_old = $xt;
    296                     }
    297                     $cord[$idx++] = $xt;
    298                     $cord[$idx++] = $yt_old;
    299                     $cord[$idx++] = $xt;
    300                     $cord[$idx++] = $yt;
    301                 }
    302                 elseif( $firstnonumeric==false ) {
    303                     $firstnonumeric = true;
    304                     $yt_first = $yt_old;
    305                     $xt_first = $xt_old;
    306                 }
    307             }
    308             else {
    309                 $tmp1=$y;
    310                 $prev=$this->coords[0][$pnts-1];
    311                 if( $tmp1==='' || $tmp1===NULL || $tmp1==='X' ) $tmp1 = 'x';
    312                 if( $prev==='' || $prev===null || $prev==='X' ) $prev = 'x';
    313 
    314                 if( is_numeric($y) || (is_string($y) && $y != '-') ) {
    315                     if( is_numeric($y) && (is_numeric($prev) || $prev === '-' ) ) {
    316                         $img->StyleLineTo($xt,$yt);
    317                     }
    318                     else {
    319                         $img->SetStartPoint($xt,$yt);
    320                     }
    321                 }
    322                 if( $this->filled && $tmp1 !== '-' ) {
    323                     if( $tmp1 === 'x' ) {
    324                         $cord[$idx++] = $cord[$idx-3];
    325                         $cord[$idx++] = $fillmin;
    326                     }
    327                     elseif( $prev === 'x' ) {
    328                         $cord[$idx++] = $xt;
    329                         $cord[$idx++] = $fillmin;
    330                         $cord[$idx++] = $xt;
    331                         $cord[$idx++] = $yt;
    332                     }
    333                     else {
    334                         $cord[$idx++] = $xt;
    335                         $cord[$idx++] = $yt;
    336                     }
    337                 }
    338                 else {
    339                     if( is_numeric($tmp1)  && (is_numeric($prev) || $prev === '-' ) ) {
    340                         $cord[$idx++] = $xt;
    341                         $cord[$idx++] = $yt;
    342                     }
    343                 }
    344             }
    345             $yt_old = $yt;
    346             $xt_old = $xt;
    347             $y_old = $y;
    348 
    349             $this->StrokeDataValue($img,$this->coords[0][$pnts],$xt,$yt);
    350 
    351             ++$pnts;
    352         }
    353 
    354         if( $this->filled  ) {
    355             $cord[$idx++] = $xt;
    356             if( $this->fillFromMax ) {
    357                 $cord[$idx++] = $yscale->scale_abs[1];
    358             }
    359             else {
    360                 if( $min > 0 || $this->fillFromMin ) {
    361                     $cord[$idx++] = $yscale->Translate($min);
    362                 }
    363                 else {
    364                     $cord[$idx++] = $yscale->Translate(0);
    365                 }
    366             }
    367             if( $this->fillgrad ) {
    368                 $img->SetLineWeight(1);
    369                 $grad = new Gradient($img);
    370                 $grad->SetNumColors($this->fillgrad_numcolors);
    371                 $grad->FilledFlatPolygon($cord,$this->fillgrad_fromcolor,$this->fillgrad_tocolor);
    372                 $img->SetLineWeight($this->weight);
    373             }
    374             else {
    375                 $img->SetColor($this->fill_color);
    376                 $img->FilledPolygon($cord);
    377             }
    378             if( $this->weight > 0 ) {
    379                 $img->SetLineWeight($this->weight);
    380                 $img->SetColor($this->color);
    381                 // Remove first and last coordinate before drawing the line
    382                 // sine we otherwise get the vertical start and end lines which
    383                 // doesn't look appropriate
    384                 $img->Polygon(array_slice($cord,2,count($cord)-4));
    385             }
    386         }
    387 
    388         if(!empty($this->filledAreas)) {
    389 
    390             $minY = $yscale->Translate($yscale->GetMinVal());
    391             $factor = ($this->step_style ? 4 : 2);
    392 
    393             for($i = 0; $i < sizeof($this->filledAreas); ++$i) {
    394                 // go through all filled area elements ordered by insertion
    395                 // fill polygon array
    396                 $areaCoords[] = $cord[$this->filledAreas[$i][0] * $factor];
    397                 $areaCoords[] = $minY;
    398 
    399                 $areaCoords =
    400                 array_merge($areaCoords,
    401                 array_slice($cord,
    402                 $this->filledAreas[$i][0] * $factor,
    403                 ($this->filledAreas[$i][1] - $this->filledAreas[$i][0] + ($this->step_style ? 0 : 1))  * $factor));
    404                 $areaCoords[] = $areaCoords[sizeof($areaCoords)-2]; // last x
    405                 $areaCoords[] = $minY; // last y
    406 
    407                 if($this->filledAreas[$i][3]) {
    408                     $img->SetColor($this->filledAreas[$i][2]);
    409                     $img->FilledPolygon($areaCoords);
    410                     $img->SetColor($this->color);
    411                 }
    412                 // Check if we should draw the frame.
    413                 // If not we still re-draw the line since it might have been
    414                 // partially overwritten by the filled area and it doesn't look
    415                 // very good.
    416                 if( $this->filledAreas[$i][4] ) {
    417                     $img->Polygon($areaCoords);
    418                 }
    419                 else {
    420                     $img->Polygon($cord);
    421                 }
    422 
    423                 $areaCoords = array();
    424             }
    425         }
    426 
    427         if( $this->mark->type == -1 || $this->mark->show == false )
    428         return;
    429 
    430         for( $pnts=0; $pnts<$numpoints; ++$pnts) {
    431 
    432             if( $exist_x ) {
    433                 $x=$this->coords[1][$pnts];
    434             }
    435             else {
    436                 $x=$pnts+$textadj;
    437             }
    438             $xt = $xscale->Translate($x);
    439             $yt = $yscale->Translate($this->coords[0][$pnts]);
    440 
    441             if( is_numeric($this->coords[0][$pnts]) ) {
    442                 if( !empty($this->csimtargets[$pnts]) ) {
    443                     if( !empty($this->csimwintargets[$pnts]) ) {
    444                         $this->mark->SetCSIMTarget($this->csimtargets[$pnts],$this->csimwintargets[$pnts]);
    445                     }
    446                     else {
    447                         $this->mark->SetCSIMTarget($this->csimtargets[$pnts]);
    448                     }
    449                     $this->mark->SetCSIMAlt($this->csimalts[$pnts]);
    450                 }
    451                 if( $exist_x ) {
    452                     $x=$this->coords[1][$pnts];
    453                 }
    454                 else {
    455                     $x=$pnts;
    456                 }
    457                 $this->mark->SetCSIMAltVal($this->coords[0][$pnts],$x);
    458                 $this->mark->Stroke($img,$xt,$yt);
    459                 $this->csimareas .= $this->mark->GetCSIMAreas();
    460             }
    461         }
     174        $idx=0;
     175        $numpoints=count($this->coords[0]);
     176        if( isset($this->coords[1]) ) {
     177            if( count($this->coords[1])!=$numpoints )
     178                JpGraphError::RaiseL(2003,count($this->coords[1]),$numpoints);
     179//("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints");
     180            else
     181                $exist_x = true;
     182        }
     183        else
     184            $exist_x = false;
     185
     186        if( $this->barcenter )
     187            $textadj = 0.5-$xscale->text_scale_off;
     188        else
     189            $textadj = 0;
     190
     191        // Find the first numeric data point
     192        $startpoint=0;
     193        while( $startpoint < $numpoints && !is_numeric($this->coords[0][$startpoint]) )
     194            ++$startpoint;
     195
     196        // Bail out if no data points
     197        if( $startpoint == $numpoints )
     198            return;
     199
     200        if( $this->iFastStroke ) {
     201            $this->FastStroke($img,$xscale,$yscale,$startpoint,$exist_x);
     202            return;
     203        }
     204
     205        if( $exist_x )
     206            $xs=$this->coords[1][$startpoint];
     207        else
     208            $xs= $textadj+$startpoint;
     209
     210        $img->SetStartPoint($xscale->Translate($xs),
     211                            $yscale->Translate($this->coords[0][$startpoint]));
     212
     213               
     214        if( $this->filled ) {
     215            $min = $yscale->GetMinVal();
     216            if( $min > 0 || $this->fillFromMin )
     217                $fillmin = $yscale->scale_abs[0];//Translate($min);
     218            else
     219                $fillmin = $yscale->Translate(0);
     220
     221            $cord[$idx++] = $xscale->Translate($xs);
     222            $cord[$idx++] = $fillmin;
     223        }
     224        $xt = $xscale->Translate($xs);
     225        $yt = $yscale->Translate($this->coords[0][$startpoint]);
     226        $cord[$idx++] = $xt;
     227        $cord[$idx++] = $yt;
     228        $yt_old = $yt;
     229        $xt_old = $xt;
     230        $y_old = $this->coords[0][$startpoint];
     231
     232        $this->value->Stroke($img,$this->coords[0][$startpoint],$xt,$yt);
     233
     234        $img->SetColor($this->color);
     235        $img->SetLineWeight($this->weight);
     236        $img->SetLineStyle($this->line_style);
     237        $pnts=$startpoint+1;
     238        $firstnonumeric = false;
     239
     240
     241        while( $pnts < $numpoints ) {
     242           
     243            if( $exist_x ) $x=$this->coords[1][$pnts];
     244            else $x=$pnts+$textadj;
     245            $xt = $xscale->Translate($x);
     246            $yt = $yscale->Translate($this->coords[0][$pnts]);
     247           
     248            $y=$this->coords[0][$pnts];
     249            if( $this->step_style ) {
     250                // To handle null values within step style we need to record the
     251                // first non numeric value so we know from where to start if the
     252                // non value is '-'.
     253                if( is_numeric($y) ) {
     254                    $firstnonumeric = false;
     255                    if( is_numeric($y_old) ) {
     256                        $img->StyleLine($xt_old,$yt_old,$xt,$yt_old);
     257                        $img->StyleLine($xt,$yt_old,$xt,$yt);
     258                    }
     259                    elseif( $y_old == '-' ) {
     260                        $img->StyleLine($xt_first,$yt_first,$xt,$yt_first);
     261                        $img->StyleLine($xt,$yt_first,$xt,$yt);                 
     262                    }
     263                    else {
     264                        $yt_old = $yt;
     265                        $xt_old = $xt;
     266                    }
     267                    $cord[$idx++] = $xt;
     268                    $cord[$idx++] = $yt_old;
     269                    $cord[$idx++] = $xt;
     270                    $cord[$idx++] = $yt;
     271                }
     272                elseif( $firstnonumeric==false ) {
     273                    $firstnonumeric = true;
     274                    $yt_first = $yt_old;
     275                    $xt_first = $xt_old;
     276                }
     277            }
     278            else {
     279                $tmp1=$y;
     280                $prev=$this->coords[0][$pnts-1];                                       
     281                if( $tmp1==='' || $tmp1===NULL || $tmp1==='X' ) $tmp1 = 'x';
     282                if( $prev==='' || $prev===null || $prev==='X' ) $prev = 'x';
     283
     284                if( is_numeric($y) || (is_string($y) && $y != '-') ) {
     285                    if( is_numeric($y) && (is_numeric($prev) || $prev === '-' ) ) {
     286                        $img->StyleLineTo($xt,$yt);
     287                    }
     288                    else {
     289                        $img->SetStartPoint($xt,$yt);
     290                    }
     291                }
     292                if( $this->filled && $tmp1 !== '-' ) {
     293                    if( $tmp1 === 'x' ) {
     294                        $cord[$idx++] = $cord[$idx-3];
     295                        $cord[$idx++] = $fillmin;
     296                    }
     297                    elseif( $prev === 'x' ) {
     298                        $cord[$idx++] = $xt;
     299                        $cord[$idx++] = $fillmin;
     300                        $cord[$idx++] = $xt;
     301                        $cord[$idx++] = $yt;                       
     302                    }
     303                    else {
     304                        $cord[$idx++] = $xt;
     305                        $cord[$idx++] = $yt;
     306                    }
     307                }
     308                else {
     309                    if( is_numeric($tmp1)  && (is_numeric($prev) || $prev === '-' ) ) {
     310                        $cord[$idx++] = $xt;
     311                        $cord[$idx++] = $yt;
     312                    }
     313                }
     314            }
     315            $yt_old = $yt;
     316            $xt_old = $xt;
     317            $y_old = $y;
     318
     319            $this->StrokeDataValue($img,$this->coords[0][$pnts],$xt,$yt);
     320
     321            ++$pnts;
     322        }       
     323
     324        if( $this->filled  ) {
     325            $cord[$idx++] = $xt;
     326            if( $min > 0 || $this->fillFromMin )
     327                $cord[$idx++] = $yscale->Translate($min);
     328            else
     329                $cord[$idx++] = $yscale->Translate(0);
     330            if( $this->fillgrad ) {
     331                $img->SetLineWeight(1);
     332                $grad = new Gradient($img);
     333                $grad->SetNumColors($this->fillgrad_numcolors);
     334                $grad->FilledFlatPolygon($cord,$this->fillgrad_fromcolor,$this->fillgrad_tocolor);
     335                $img->SetLineWeight($this->weight);
     336            }
     337            else {
     338                $img->SetColor($this->fill_color);     
     339                $img->FilledPolygon($cord);
     340            }
     341            if( $this->line_weight > 0 ) {
     342                $img->SetColor($this->color);
     343                $img->Polygon($cord);
     344            }
     345        }
     346
     347        if(!empty($this->filledAreas)) {
     348
     349            $minY = $yscale->Translate($yscale->GetMinVal());
     350            $factor = ($this->step_style ? 4 : 2);
     351
     352            for($i = 0; $i < sizeof($this->filledAreas); ++$i) {
     353                // go through all filled area elements ordered by insertion
     354                // fill polygon array
     355                $areaCoords[] = $cord[$this->filledAreas[$i][0] * $factor];
     356                $areaCoords[] = $minY;
     357
     358                $areaCoords =
     359                    array_merge($areaCoords,
     360                                array_slice($cord,
     361                                            $this->filledAreas[$i][0] * $factor,
     362                                            ($this->filledAreas[$i][1] - $this->filledAreas[$i][0] + ($this->step_style ? 0 : 1))  * $factor));
     363                $areaCoords[] = $areaCoords[sizeof($areaCoords)-2]; // last x
     364                $areaCoords[] = $minY; // last y
     365           
     366                if($this->filledAreas[$i][3]) {
     367                    $img->SetColor($this->filledAreas[$i][2]);
     368                    $img->FilledPolygon($areaCoords);
     369                    $img->SetColor($this->color);
     370                }
     371                // Check if we should draw the frame.
     372                // If not we still re-draw the line since it might have been
     373                // partially overwritten by the filled area and it doesn't look
     374                // very good.
     375                // TODO: The behaviour is undefined if the line does not have
     376                // any line at the position of the area.
     377                if( $this->filledAreas[$i][4] )
     378                    $img->Polygon($areaCoords);
     379                else
     380                    $img->Polygon($cord);
     381
     382                $areaCoords = array();
     383            }
     384        }       
     385
     386        if( $this->mark->type == -1 || $this->mark->show == false )
     387            return;
     388
     389        for( $pnts=0; $pnts<$numpoints; ++$pnts) {
     390
     391            if( $exist_x ) $x=$this->coords[1][$pnts];
     392            else $x=$pnts+$textadj;
     393            $xt = $xscale->Translate($x);
     394            $yt = $yscale->Translate($this->coords[0][$pnts]);
     395
     396            if( is_numeric($this->coords[0][$pnts]) ) {
     397                if( !empty($this->csimtargets[$pnts]) ) {
     398                    if( !empty($this->csimwintargets[$pnts]) ) {
     399                        $this->mark->SetCSIMTarget($this->csimtargets[$pnts],$this->csimwintargets[$pnts]);
     400                    }
     401                    else {
     402                        $this->mark->SetCSIMTarget($this->csimtargets[$pnts]);
     403                    }
     404                    $this->mark->SetCSIMAlt($this->csimalts[$pnts]);
     405                }
     406                if( $exist_x )
     407                    $x=$this->coords[1][$pnts];
     408                else
     409                    $x=$pnts;
     410                $this->mark->SetCSIMAltVal($this->coords[0][$pnts],$x);
     411                $this->mark->Stroke($img,$xt,$yt);     
     412                $this->csimareas .= $this->mark->GetCSIMAreas();
     413            }
     414        }
    462415    }
    463416} // Class
     
    466419//===================================================
    467420// CLASS AccLinePlot
    468 // Description:
     421// Description: 
    469422//===================================================
    470423class AccLinePlot extends Plot {
    471424    protected $plots=null,$nbrplots=0;
    472425    private $iStartEndZero=true;
    473     //---------------
    474     // CONSTRUCTOR
    475     function __construct($plots) {
     426//---------------
     427// CONSTRUCTOR
     428    function AccLinePlot($plots) {
    476429        $this->plots = $plots;
    477         $this->nbrplots = count($plots);
    478         $this->numpoints = $plots[0]->numpoints;
    479 
    480         // Verify that all plots have the same number of data points
    481         for( $i=1; $i < $this->nbrplots; ++$i ) {
    482             if( $plots[$i]->numpoints != $this->numpoints ) {
    483                 JpGraphError::RaiseL(10003);//('Each plot in an accumulated lineplot must have the same number of data points',0)
    484             }
    485         }
    486 
    487         for($i=0; $i < $this->nbrplots; ++$i ) {
    488             $this->LineInterpolate($this->plots[$i]->coords[0]);
    489         }
    490     }
    491 
    492     //---------------
    493     // PUBLIC METHODS
     430        $this->nbrplots = count($plots);
     431        $this->numpoints = $plots[0]->numpoints;
     432
     433        // Verify that all plots have the same number of data points
     434        for( $i=1; $i < $this->nbrplots; ++$i ) {
     435            if( $plots[$i]->numpoints != $this->numpoints ) {
     436                JpGraphError::RaiseL(10003);//('Each plot in an accumulated lineplot must have the same number of data points',0)
     437            }
     438        }
     439
     440        for($i=0; $i < $this->nbrplots; ++$i ) {
     441            $this->LineInterpolate($this->plots[$i]->coords[0]);
     442        }       
     443    }
     444
     445//---------------
     446// PUBLIC METHODS       
    494447    function Legend($graph) {
    495         foreach( $this->plots as $p ) {
    496             $p->DoLegend($graph);
    497         }
    498     }
    499 
     448        foreach( $this->plots as $p )
     449            $p->DoLegend($graph);
     450    }
     451       
    500452    function Max() {
    501         list($xmax) = $this->plots[0]->Max();
    502         $nmax=0;
    503         $n = count($this->plots);
    504         for($i=0; $i < $n; ++$i) {
    505             $nc = count($this->plots[$i]->coords[0]);
    506             $nmax = max($nmax,$nc);
    507             list($x) = $this->plots[$i]->Max();
    508             $xmax = Max($xmax,$x);
    509         }
    510         for( $i = 0; $i < $nmax; $i++ ) {
    511             // Get y-value for line $i by adding the
    512             // individual bars from all the plots added.
    513             // It would be wrong to just add the
    514             // individual plots max y-value since that
    515             // would in most cases give to large y-value.
    516             $y=$this->plots[0]->coords[0][$i];
    517             for( $j = 1; $j < $this->nbrplots; $j++ ) {
    518                 $y += $this->plots[ $j ]->coords[0][$i];
    519             }
    520             $ymax[$i] = $y;
    521         }
    522         $ymax = max($ymax);
    523         return array($xmax,$ymax);
    524     }
     453        list($xmax) = $this->plots[0]->Max();
     454        $nmax=0;
     455        $n = count($this->plots);
     456        for($i=0; $i < $n; ++$i) {
     457            $nc = count($this->plots[$i]->coords[0]);
     458            $nmax = max($nmax,$nc);
     459            list($x) = $this->plots[$i]->Max();
     460            $xmax = Max($xmax,$x);
     461        }
     462        for( $i = 0; $i < $nmax; $i++ ) {
     463            // Get y-value for line $i by adding the
     464            // individual bars from all the plots added.
     465            // It would be wrong to just add the
     466            // individual plots max y-value since that
     467            // would in most cases give to large y-value.
     468            $y=$this->plots[0]->coords[0][$i];
     469            for( $j = 1; $j < $this->nbrplots; $j++ ) {
     470                $y += $this->plots[ $j ]->coords[0][$i];
     471            }
     472            $ymax[$i] = $y;
     473        }
     474        $ymax = max($ymax);
     475        return array($xmax,$ymax);
     476    }   
    525477
    526478    function Min() {
    527         $nmax=0;
    528         list($xmin,$ysetmin) = $this->plots[0]->Min();
    529         $n = count($this->plots);
    530         for($i=0; $i < $n; ++$i) {
    531             $nc = count($this->plots[$i]->coords[0]);
    532             $nmax = max($nmax,$nc);
    533             list($x,$y) = $this->plots[$i]->Min();
    534             $xmin = Min($xmin,$x);
    535             $ysetmin = Min($y,$ysetmin);
    536         }
    537         for( $i = 0; $i < $nmax; $i++ ) {
    538             // Get y-value for line $i by adding the
    539             // individual bars from all the plots added.
    540             // It would be wrong to just add the
    541             // individual plots min y-value since that
    542             // would in most cases give to small y-value.
    543             $y=$this->plots[0]->coords[0][$i];
    544             for( $j = 1; $j < $this->nbrplots; $j++ ) {
    545                 $y += $this->plots[ $j ]->coords[0][$i];
    546             }
    547             $ymin[$i] = $y;
    548         }
    549         $ymin = Min($ysetmin,Min($ymin));
    550         return array($xmin,$ymin);
     479        $nmax=0;
     480        list($xmin,$ysetmin) = $this->plots[0]->Min();
     481        $n = count($this->plots);
     482        for($i=0; $i < $n; ++$i) {
     483            $nc = count($this->plots[$i]->coords[0]);
     484            $nmax = max($nmax,$nc);
     485            list($x,$y) = $this->plots[$i]->Min();
     486            $xmin = Min($xmin,$x);
     487            $ysetmin = Min($y,$ysetmin);
     488        }
     489        for( $i = 0; $i < $nmax; $i++ ) {
     490            // Get y-value for line $i by adding the
     491            // individual bars from all the plots added.
     492            // It would be wrong to just add the
     493            // individual plots min y-value since that
     494            // would in most cases give to small y-value.
     495            $y=$this->plots[0]->coords[0][$i];
     496            for( $j = 1; $j < $this->nbrplots; $j++ ) {
     497                $y += $this->plots[ $j ]->coords[0][$i];
     498            }
     499            $ymin[$i] = $y;
     500        }
     501        $ymin = Min($ysetmin,Min($ymin));
     502        return array($xmin,$ymin);
    551503    }
    552504
     
    554506    function PreStrokeAdjust($graph) {
    555507
    556         // If another plot type have already adjusted the
    557         // offset we don't touch it.
    558         // (We check for empty in case the scale is  a log scale
    559         // and hence doesn't contain any xlabel_offset)
    560 
    561         if( empty($graph->xaxis->scale->ticks->xlabel_offset) ||
    562         $graph->xaxis->scale->ticks->xlabel_offset == 0 ) {
    563             if( $this->center ) {
    564                 ++$this->numpoints;
    565                 $a=0.5; $b=0.5;
    566             } else {
    567                 $a=0; $b=0;
    568             }
    569             $graph->xaxis->scale->ticks->SetXLabelOffset($a);
    570             $graph->SetTextScaleOff($b);
    571             $graph->xaxis->scale->ticks->SupressMinorTickMarks();
    572         }
    573 
     508        // If another plot type have already adjusted the
     509        // offset we don't touch it.
     510        // (We check for empty in case the scale is  a log scale
     511        // and hence doesn't contain any xlabel_offset)
     512       
     513        if( empty($graph->xaxis->scale->ticks->xlabel_offset) ||
     514            $graph->xaxis->scale->ticks->xlabel_offset == 0 ) {
     515            if( $this->center ) {
     516                ++$this->numpoints;
     517                $a=0.5; $b=0.5;
     518            } else {
     519                $a=0; $b=0;
     520            }
     521            $graph->xaxis->scale->ticks->SetXLabelOffset($a);
     522            $graph->SetTextScaleOff($b);                                               
     523            $graph->xaxis->scale->ticks->SupressMinorTickMarks();
     524        }
     525       
    574526    }
    575527
    576528    function SetInterpolateMode($aIntMode) {
    577         $this->iStartEndZero=$aIntMode;
     529        $this->iStartEndZero=$aIntMode;
    578530    }
    579531
     
    583535    function LineInterpolate(&$aData) {
    584536
    585         $n=count($aData);
    586         $i=0;
    587 
    588         // If first point is undefined we will set it to the same as the first
    589         // valid data
    590         if( $aData[$i]==='-' ) {
    591             // Find the first valid data
    592             while( $i < $n && $aData[$i]==='-' ) {
    593                 ++$i;
    594             }
    595             if( $i < $n ) {
    596                 for($j=0; $j < $i; ++$j ) {
    597                     if( $this->iStartEndZero )
    598                     $aData[$i] = 0;
    599                     else
    600                     $aData[$j] = $aData[$i];
    601                 }
    602             }
    603             else {
    604                 // All '-' => Error
    605                 return false;
    606             }
    607         }
    608 
    609         while($i < $n) {
    610             while( $i < $n && $aData[$i] !== '-' ) {
    611                 ++$i;
    612             }
    613             if( $i < $n ) {
    614                 $pstart=$i-1;
    615 
    616                 // Now see how long this segment of '-' are
    617                 while( $i < $n && $aData[$i] === '-' ) {
    618                     ++$i;
    619                 }
    620                 if( $i < $n ) {
    621                     $pend=$i;
    622                     $size=$pend-$pstart;
    623                     $k=($aData[$pend]-$aData[$pstart])/$size;
    624                     // Replace the segment of '-' with a linear interpolated value.
    625                     for($j=1; $j < $size; ++$j ) {
    626                         $aData[$pstart+$j] = $aData[$pstart] + $j*$k ;
    627                     }
    628                 }
    629                 else {
    630                     // There are no valid end point. The '-' goes all the way to the end
    631                     // In that case we just set all the remaining values the the same as the
    632                     // last valid data point.
    633                     for( $j=$pstart+1; $j < $n; ++$j )
    634                     if( $this->iStartEndZero ) {
    635                         $aData[$j] = 0;
    636                     }
    637                     else {
    638                         $aData[$j] = $aData[$pstart] ;
    639                     }
    640                 }
    641             }
    642         }
    643         return true;
    644     }
     537        $n=count($aData);
     538        $i=0;
     539   
     540        // If first point is undefined we will set it to the same as the first
     541        // valid data
     542        if( $aData[$i]==='-' ) {
     543            // Find the first valid data
     544            while( $i < $n && $aData[$i]==='-' ) {
     545                ++$i;
     546            }
     547            if( $i < $n ) {
     548                for($j=0; $j < $i; ++$j ) {
     549                    if( $this->iStartEndZero )
     550                        $aData[$i] = 0;
     551                    else
     552                        $aData[$j] = $aData[$i];
     553                }
     554            }
     555            else {
     556                // All '-' => Error
     557                return false;
     558            }
     559        }
     560
     561        while($i < $n) {
     562            while( $i < $n && $aData[$i] !== '-' ) {
     563                ++$i;
     564            }
     565            if( $i < $n ) {
     566                $pstart=$i-1;
     567
     568                // Now see how long this segment of '-' are
     569                while( $i < $n && $aData[$i] === '-' )
     570                    ++$i;
     571                if( $i < $n ) {
     572                    $pend=$i;
     573                    $size=$pend-$pstart;
     574                    $k=($aData[$pend]-$aData[$pstart])/$size;
     575                    // Replace the segment of '-' with a linear interpolated value.
     576                    for($j=1; $j < $size; ++$j ) {
     577                        $aData[$pstart+$j] = $aData[$pstart] + $j*$k ;
     578                    }
     579                }
     580                else {
     581                    // There are no valid end point. The '-' goes all the way to the end
     582                    // In that case we just set all the remaining values the the same as the
     583                    // last valid data point.
     584                    for( $j=$pstart+1; $j < $n; ++$j )
     585                        if( $this->iStartEndZero )
     586                            $aData[$j] = 0;
     587                        else
     588                            $aData[$j] = $aData[$pstart] ;             
     589                }
     590            }
     591        }
     592        return true;
     593    }
     594
     595
    645596
    646597    // To avoid duplicate of line drawing code here we just
     
    651602    // since this method would have a side effect.
    652603    function Stroke($img,$xscale,$yscale) {
    653         $img->SetLineWeight($this->weight);
    654         $this->numpoints = count($this->plots[0]->coords[0]);
    655         // Allocate array
    656         $coords[$this->nbrplots][$this->numpoints]=0;
    657         for($i=0; $i<$this->numpoints; $i++) {
    658             $coords[0][$i]=$this->plots[0]->coords[0][$i];
    659             $accy=$coords[0][$i];
    660             for($j=1; $j<$this->nbrplots; ++$j ) {
    661                 $coords[$j][$i] = $this->plots[$j]->coords[0][$i]+$accy;
    662                 $accy = $coords[$j][$i];
    663             }
    664         }
    665         for($j=$this->nbrplots-1; $j>=0; --$j) {
    666             $p=$this->plots[$j];
    667             for( $i=0; $i<$this->numpoints; ++$i) {
    668                 $tmp[$i]=$p->coords[0][$i];
    669                 $p->coords[0][$i]=$coords[$j][$i];
    670             }
    671             $p->Stroke($img,$xscale,$yscale);
    672             for( $i=0; $i<$this->numpoints; ++$i) {
    673                 $p->coords[0][$i]=$tmp[$i];
    674             }
    675             $p->coords[0][]=$tmp;
    676         }
     604        $img->SetLineWeight($this->weight);
     605        $this->numpoints = count($this->plots[0]->coords[0]);
     606        // Allocate array
     607        $coords[$this->nbrplots][$this->numpoints]=0;
     608        for($i=0; $i<$this->numpoints; $i++) {
     609            $coords[0][$i]=$this->plots[0]->coords[0][$i];
     610            $accy=$coords[0][$i];
     611            for($j=1; $j<$this->nbrplots; ++$j ) {
     612                $coords[$j][$i] = $this->plots[$j]->coords[0][$i]+$accy;
     613                $accy = $coords[$j][$i];
     614            }
     615        }
     616        for($j=$this->nbrplots-1; $j>=0; --$j) {
     617            $p=$this->plots[$j];
     618            for( $i=0; $i<$this->numpoints; ++$i) {
     619                $tmp[$i]=$p->coords[0][$i];
     620                $p->coords[0][$i]=$coords[$j][$i];
     621            }
     622            $p->Stroke($img,$xscale,$yscale);
     623            for( $i=0; $i<$this->numpoints; ++$i)
     624                $p->coords[0][$i]=$tmp[$i];
     625            $p->coords[0][]=$tmp;
     626        }
    677627    }
    678628} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_log.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_LOG.PHP
    4  // Description: Log scale plot extension for JpGraph
    5  // Created:     2001-01-08
    6  // Ver:         $Id: jpgraph_log.php 1106 2009-02-22 20:16:35Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_LOG.PHP
     4// Description: Log scale plot extension for JpGraph
     5// Created:     2001-01-08
     6// Ver:         $Id: jpgraph_log.php 957 2007-12-01 14:00:29Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212DEFINE('LOGLABELS_PLAIN',0);
     
    1818//===================================================
    1919class LogScale extends LinearScale {
    20     //---------------
    21     // CONSTRUCTOR
     20//---------------
     21// CONSTRUCTOR
    2222
    2323    // Log scale is specified using the log of min and max
    24     function __construct($min,$max,$type="y") {
    25         parent::__construct($min,$max,$type);
    26         $this->ticks = new LogTicks();
    27         $this->name = 'log';
    28     }
    29 
    30     //----------------
    31     // PUBLIC METHODS
     24    function LogScale($min,$max,$type="y") {
     25        $this->LinearScale($min,$max,$type);
     26        $this->ticks = new LogTicks();
     27        $this->name = 'log';
     28    }
     29
     30//----------------
     31// PUBLIC METHODS       
    3232
    3333    // Translate between world and screen
    3434    function Translate($a) {
    35         if( !is_numeric($a) ) {
    36             if( $a != '' && $a != '-' && $a != 'x' ) {
    37                 JpGraphError::RaiseL(11001);
    38                 // ('Your data contains non-numeric values.');
    39             }
    40             return 1;
    41         }
    42         if( $a < 0 ) {
    43             JpGraphError::RaiseL(11002);
    44             //("Negative data values can not be used in a log scale.");
    45             exit(1);
    46         }
    47         if( $a==0 ) $a=1;
    48         $a=log10($a);
    49         return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor);
     35        if( !is_numeric($a) ) {
     36            if( $a != '' && $a != '-' && $a != 'x' )
     37                JpGraphError::RaiseL(11001);
     38//('Your data contains non-numeric values.');
     39            return 1;
     40        }
     41        if( $a < 0 ) {
     42            JpGraphError::RaiseL(11002);
     43//("Negative data values can not be used in a log scale.");
     44            exit(1);
     45        }
     46        if( $a==0 ) $a=1;
     47        $a=log10($a);
     48        return ceil($this->off + ($a*1.0 - $this->scale[0]) * $this->scale_factor);
    5049    }
    5150
    5251    // Relative translate (don't include offset) usefull when we just want
    53     // to know the relative position (in pixels) on the axis
     52    // to know the relative position (in pixels) on the axis   
    5453    function RelTranslate($a) {
    55         if( !is_numeric($a) ) {
    56             if( $a != '' && $a != '-' && $a != 'x' ) {
    57                 JpGraphError::RaiseL(11001);
    58                 //('Your data contains non-numeric values.');
    59             }
    60             return 1;
    61         }
    62         if( $a==0 ) {
    63             $a=1;
    64         }
    65         $a=log10($a);
    66         return round(($a*1.0 - $this->scale[0]) * $this->scale_factor);
    67     }
    68 
     54        if( !is_numeric($a) ) {
     55            if( $a != '' && $a != '-' && $a != 'x' )
     56                JpGraphError::RaiseL(11001);
     57//('Your data contains non-numeric values.');
     58            return 1;
     59        }
     60        if( $a==0 ) $a=1;
     61        $a=log10($a);
     62        return round(($a*1.0 - $this->scale[0]) * $this->scale_factor);
     63    }
     64               
    6965    // Use bcpow() for increased precision
    7066    function GetMinVal() {
    71         if( function_exists("bcpow") ) {
    72             return round(bcpow(10,$this->scale[0],15),14);
    73         }
    74         else {
    75             return round(pow(10,$this->scale[0]),14);
    76         }
    77     }
    78 
     67        if( function_exists("bcpow") )
     68            return round(bcpow(10,$this->scale[0],15),14);
     69        else
     70            return round(pow(10,$this->scale[0]),14);
     71    }
     72       
    7973    function GetMaxVal() {
    80         if( function_exists("bcpow") ) {
    81             return round(bcpow(10,$this->scale[1],15),14);
    82         }
    83         else {
    84             return round(pow(10,$this->scale[1]),14);
    85         }
    86     }
    87 
     74        if( function_exists("bcpow") )
     75            return round(bcpow(10,$this->scale[1],15),14);
     76        else
     77            return round(pow(10,$this->scale[1]),14);
     78    }
     79       
    8880    // Logarithmic autoscaling is much simplier since we just
    8981    // set the min and max to logs of the min and max values.
     
    9284    // signature as the linear counterpart.
    9385    function AutoScale($img,$min,$max,$maxsteps,$majend=true) {
    94         if( $min==0 ) $min=1;
    95 
    96         if( $max <= 0 ) {
    97             JpGraphError::RaiseL(11004);
    98             //('Scale error for logarithmic scale. You have a problem with your data values. The max value must be greater than 0. It is mathematically impossible to have 0 in a logarithmic scale.');
    99         }
    100         if( is_numeric($this->autoscale_min) ) {
    101             $smin = round($this->autoscale_min);
    102             $smax = ceil(log10($max));
    103             if( $min >= $max ) {
    104                 JpGraphError::RaiseL(25071);//('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.');
    105             }
    106         }
    107         else {
    108             $smin = floor(log10($min));
    109             if( is_numeric($this->autoscale_max) ) {
    110                 $smax = round($this->autoscale_max);
    111                 if( $smin >= $smax ) {
    112                     JpGraphError::RaiseL(25072);//('You have specified a max value with SetAutoMax() which is smaller than the miminum value used for the scale. This is not possible.');
    113                 }
    114             }
    115             else
    116             $smax = ceil(log10($max));
    117         }
    118 
    119         $this->Update($img,$smin,$smax);
    120     }
    121     //---------------
    122     // PRIVATE METHODS
     86        if( $min==0 ) $min=1;
     87       
     88        if( $max <= 0 ) {
     89            JpGraphError::RaiseL(11004);
     90//('Scale error for logarithmic scale. You have a problem with your data values. The max value must be greater than 0. It is mathematically impossible to have 0 in a logarithmic scale.');
     91        }
     92        if( is_numeric($this->autoscale_min) ) {
     93            $smin = round($this->autoscale_min);
     94            $smax = ceil(log10($max));
     95            if( $min >= $max ) {
     96                JpGraphError::RaiseL(25071);//('You have specified a min value with SetAutoMin() which is larger than the maximum value used for the scale. This is not possible.');
     97            }
     98        }
     99        else {
     100            $smin = floor(log10($min));
     101            if( is_numeric($this->autoscale_max) ) {
     102                $smax = round($this->autoscale_max);
     103                if( $smin >= $smax ) {
     104                    JpGraphError::RaiseL(25072);//('You have specified a max value with SetAutoMax() which is smaller than the miminum value used for the scale. This is not possible.');
     105                }
     106            }
     107            else
     108                $smax = ceil(log10($max));
     109        }
     110
     111        $this->Update($img,$smin,$smax);                                       
     112    }
     113//---------------
     114// PRIVATE METHODS     
    123115} // Class
    124116
    125117//===================================================
    126118// CLASS LogTicks
    127 // Description:
     119// Description: 
    128120//===================================================
    129121class LogTicks extends Ticks{
    130122    private $label_logtype=LOGLABELS_MAGNITUDE;
    131123    private $ticklabels_pos = array();
    132     //---------------
    133     // CONSTRUCTOR
    134     function __construct() {
    135     }
    136     //---------------
    137     // PUBLIC METHODS
     124//---------------
     125// CONSTRUCTOR
     126    function LogTicks() {
     127    }
     128//---------------
     129// PUBLIC METHODS       
    138130    function IsSpecified() {
    139         return true;
     131        return true;
    140132    }
    141133
    142134    function SetLabelLogType($aType) {
    143         $this->label_logtype = $aType;
    144     }
    145 
     135        $this->label_logtype = $aType;
     136    }
     137       
    146138    // For log scale it's meaningless to speak about a major step
    147139    // We just return -1 to make the framework happy (specifically
    148140    // StrokeLabels() )
    149141    function GetMajor() {
    150         return -1;
     142        return -1;
    151143    }
    152144
    153145    function SetTextLabelStart($aStart) {
    154         JpGraphError::RaiseL(11005);
    155         //('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.');
     146        JpGraphError::RaiseL(11005);
     147//('Specifying tick interval for a logarithmic scale is undefined. Remove any calls to SetTextLabelStart() or SetTextTickInterval() on the logarithmic scale.');
    156148    }
    157149
    158150    function SetXLabelOffset($dummy) {
    159         // For log scales we dont care about XLabel offset
     151        // For log scales we dont care about XLabel offset
    160152    }
    161153
     
    165157    // absolute x-position.
    166158    function Stroke($img,$scale,$pos) {
    167         $start = $scale->GetMinVal();
    168         $limit = $scale->GetMaxVal();
    169         $nextMajor = 10*$start;
    170         $step = $nextMajor / 10.0;
    171 
    172 
    173         $img->SetLineWeight($this->weight);
    174 
    175         if( $scale->type == "y" ) {
    176             // member direction specified if the ticks should be on
    177             // left or right side.
    178             $a=$pos + $this->direction*$this->GetMinTickAbsSize();
    179             $a2=$pos + $this->direction*$this->GetMajTickAbsSize();
    180              
    181             $count=1;
    182             $this->maj_ticks_pos[0]=$scale->Translate($start);
    183             $this->maj_ticklabels_pos[0]=$scale->Translate($start);
    184             if( $this->supress_first )
    185             $this->maj_ticks_label[0]="";
    186             else {
    187                 if( $this->label_formfunc != '' ) {
    188                     $f = $this->label_formfunc;
    189                     $this->maj_ticks_label[0]=call_user_func($f,$start);
    190                 }
    191                 elseif( $this->label_logtype == LOGLABELS_PLAIN ) {
    192                     $this->maj_ticks_label[0]=$start;
    193                 }
    194                 else {
    195                     $this->maj_ticks_label[0]='10^'.round(log10($start));
    196                 }
    197             }
    198             $i=1;
    199             for($y=$start; $y<=$limit; $y+=$step,++$count  ) {
    200                 $ys=$scale->Translate($y);
    201                 $this->ticks_pos[]=$ys;
    202                 $this->ticklabels_pos[]=$ys;
    203                 if( $count % 10 == 0 ) {
    204                     if( !$this->supress_tickmarks ) {
    205                         if( $this->majcolor!="" ) {
    206                             $img->PushColor($this->majcolor);
    207                             $img->Line($pos,$ys,$a2,$ys);
    208                             $img->PopColor();
    209                         }
    210                         else {
    211                             $img->Line($pos,$ys,$a2,$ys);
    212                         }
    213                     }
    214 
    215                     $this->maj_ticks_pos[$i]=$ys;
    216                     $this->maj_ticklabels_pos[$i]=$ys;
    217 
    218                     if( $this->label_formfunc != '' ) {
    219                         $f = $this->label_formfunc;
    220                         $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);
    221                     }
    222                     elseif( $this->label_logtype == 0 ) {
    223                         $this->maj_ticks_label[$i]=$nextMajor;
    224                     }
    225                     else {
    226                         $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
    227                     }
    228                     ++$i;
    229                     $nextMajor *= 10;
    230                     $step *= 10;
    231                     $count=1;
    232                 }
    233                 else {
    234                     if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
    235                         if( $this->mincolor!="" ) {
    236                             $img->PushColor($this->mincolor);
    237                         }
    238                         $img->Line($pos,$ys,$a,$ys);
    239                         if( $this->mincolor!="" ) {
    240                             $img->PopColor();
    241                         }
    242                     }
    243                 }
    244             }
    245         }
    246         else {
    247             $a=$pos - $this->direction*$this->GetMinTickAbsSize();
    248             $a2=$pos - $this->direction*$this->GetMajTickAbsSize();
    249             $count=1;
    250             $this->maj_ticks_pos[0]=$scale->Translate($start);
    251             $this->maj_ticklabels_pos[0]=$scale->Translate($start);
    252             if( $this->supress_first ) {
    253                 $this->maj_ticks_label[0]="";
    254             }
    255             else {
    256                 if( $this->label_formfunc != '' ) {
    257                     $f = $this->label_formfunc;
    258                     $this->maj_ticks_label[0]=call_user_func($f,$start);
    259                 }
    260                 elseif( $this->label_logtype == 0 ) {
    261                     $this->maj_ticks_label[0]=$start;
    262                 }
    263                 else {
    264                     $this->maj_ticks_label[0]='10^'.round(log10($start));
    265                 }
    266             }
    267             $i=1;
    268             for($x=$start; $x<=$limit; $x+=$step,++$count  ) {
    269                 $xs=$scale->Translate($x);
    270                 $this->ticks_pos[]=$xs;
    271                 $this->ticklabels_pos[]=$xs;
    272                 if( $count % 10 == 0 ) {
    273                     if( !$this->supress_tickmarks ) {
    274                         $img->Line($xs,$pos,$xs,$a2);
    275                     }
    276                     $this->maj_ticks_pos[$i]=$xs;
    277                     $this->maj_ticklabels_pos[$i]=$xs;
    278 
    279                     if( $this->label_formfunc != '' ) {
    280                         $f = $this->label_formfunc;
    281                         $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);
    282                     }
    283                     elseif( $this->label_logtype == 0 ) {
    284                         $this->maj_ticks_label[$i]=$nextMajor;
    285                     }
    286                     else {
    287                         $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
    288                     }
    289                     ++$i;
    290                     $nextMajor *= 10;
    291                     $step *= 10;
    292                     $count=1;
    293                 }
    294                 else {
    295                     if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
    296                         $img->Line($xs,$pos,$xs,$a);
    297                     }
    298                 }
    299             }
    300         }
    301         return true;
     159        $start = $scale->GetMinVal();
     160        $limit = $scale->GetMaxVal();
     161        $nextMajor = 10*$start;
     162        $step = $nextMajor / 10.0;
     163               
     164               
     165        $img->SetLineWeight($this->weight);                     
     166               
     167        if( $scale->type == "y" ) {
     168            // member direction specified if the ticks should be on
     169            // left or right side.
     170            $a=$pos + $this->direction*$this->GetMinTickAbsSize();
     171            $a2=$pos + $this->direction*$this->GetMajTickAbsSize();     
     172                       
     173            $count=1;
     174            $this->maj_ticks_pos[0]=$scale->Translate($start);
     175            $this->maj_ticklabels_pos[0]=$scale->Translate($start);
     176            if( $this->supress_first )
     177                $this->maj_ticks_label[0]="";
     178            else {
     179                if( $this->label_formfunc != '' ) {
     180                    $f = $this->label_formfunc;
     181                    $this->maj_ticks_label[0]=call_user_func($f,$start);       
     182                }
     183                elseif( $this->label_logtype == LOGLABELS_PLAIN )
     184                    $this->maj_ticks_label[0]=$start;   
     185                else
     186                    $this->maj_ticks_label[0]='10^'.round(log10($start));
     187            }
     188            $i=1;
     189            for($y=$start; $y<=$limit; $y+=$step,++$count  ) {
     190                $ys=$scale->Translate($y);     
     191                $this->ticks_pos[]=$ys;
     192                $this->ticklabels_pos[]=$ys;
     193                if( $count % 10 == 0 ) {
     194                    if( !$this->supress_tickmarks ) {
     195                        if( $this->majcolor!="" ) {
     196                            $img->PushColor($this->majcolor);
     197                            $img->Line($pos,$ys,$a2,$ys);
     198                            $img->PopColor();
     199                        }
     200                        else
     201                            $img->Line($pos,$ys,$a2,$ys);
     202                    }
     203
     204                    $this->maj_ticks_pos[$i]=$ys;
     205                    $this->maj_ticklabels_pos[$i]=$ys;
     206                   
     207                    if( $this->label_formfunc != '' ) {
     208                        $f = $this->label_formfunc;
     209                        $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);       
     210                    }
     211                    elseif( $this->label_logtype == 0 )
     212                        $this->maj_ticks_label[$i]=$nextMajor; 
     213                    else
     214                        $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
     215                    ++$i;                                               
     216                    $nextMajor *= 10;
     217                    $step *= 10;       
     218                    $count=1;                           
     219                }
     220                else {
     221                    if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
     222                        if( $this->mincolor!="" ) $img->PushColor($this->mincolor);
     223                        $img->Line($pos,$ys,$a,$ys);           
     224                        if( $this->mincolor!="" ) $img->PopColor();
     225                    }
     226                }
     227            }           
     228        }
     229        else {
     230            $a=$pos - $this->direction*$this->GetMinTickAbsSize();
     231            $a2=$pos - $this->direction*$this->GetMajTickAbsSize();     
     232            $count=1;
     233            $this->maj_ticks_pos[0]=$scale->Translate($start);
     234            $this->maj_ticklabels_pos[0]=$scale->Translate($start);
     235            if( $this->supress_first )
     236                $this->maj_ticks_label[0]="";
     237            else {
     238                if( $this->label_formfunc != '' ) {
     239                    $f = $this->label_formfunc;
     240                    $this->maj_ticks_label[0]=call_user_func($f,$start);       
     241                }
     242                elseif( $this->label_logtype == 0 )
     243                    $this->maj_ticks_label[0]=$start;   
     244                else
     245                    $this->maj_ticks_label[0]='10^'.round(log10($start));
     246            }
     247            $i=1;                       
     248            for($x=$start; $x<=$limit; $x+=$step,++$count  ) {
     249                $xs=$scale->Translate($x);     
     250                $this->ticks_pos[]=$xs;
     251                $this->ticklabels_pos[]=$xs;
     252                if( $count % 10 == 0 ) {
     253                    if( !$this->supress_tickmarks ) {
     254                        $img->Line($xs,$pos,$xs,$a2);
     255                    }
     256                    $this->maj_ticks_pos[$i]=$xs;
     257                    $this->maj_ticklabels_pos[$i]=$xs;
     258
     259                    if( $this->label_formfunc != '' ) {
     260                        $f = $this->label_formfunc;
     261                        $this->maj_ticks_label[$i]=call_user_func($f,$nextMajor);       
     262                    }
     263                    elseif( $this->label_logtype == 0 )
     264                        $this->maj_ticks_label[$i]=$nextMajor; 
     265                    else
     266                        $this->maj_ticks_label[$i]='10^'.round(log10($nextMajor));
     267                    ++$i;
     268                    $nextMajor *= 10;
     269                    $step *= 10;       
     270                    $count=1;                           
     271                }
     272                else {
     273                    if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
     274                        $img->Line($xs,$pos,$xs,$a);           
     275                    }
     276                }
     277            }           
     278        }
     279        return true;
    302280    }
    303281} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_mgraph.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_MGRAPH.PHP
    4  // Description: Class to handle multiple graphs in the same image
    5  // Created:     2006-01-15
    6  // Ver:         $Id: jpgraph_mgraph.php 1770 2009-08-17 06:10:22Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_MGRAPH.PHP
     4// Description: Class to handle multiple graphs in the same image
     5// Created:     2006-01-15
     6// Ver:         $Id: jpgraph_mgraph.php 1012 2008-06-23 15:02:15Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212//=============================================================================
    1313// CLASS MGraph
    14 // Description: Create a container image that can hold several graph
     14// Description: Create a container image that can hold several graph 
    1515//=============================================================================
    1616class MGraph {
    17 
    18     public $title = null, $subtitle = null, $subsubtitle = null;
    1917
    2018    protected $img=NULL;
    2119    protected $iCnt=0,$iGraphs = array(); // image_handle, x, y, fx, fy, sizex, sizey
    2220    protected $iFillColor='white', $iCurrentColor=0;
    23     protected $lm=4,$rm=4,$tm=4,$bm=4;
     21    protected $lm=0,$rm=0,$tm=0,$bm=0;
    2422    protected $iDoFrame = FALSE, $iFrameColor = 'black', $iFrameWeight = 1;
    2523    protected $iLineWeight = 1;
    2624    protected $expired=false;
    27     protected $cache=null,$cache_name = '',$inline=true;
    28     protected $image_format='png',$image_quality=75;
     25    protected $img_format='png',$image_quality=75;
    2926    protected $iWidth=NULL,$iHeight=NULL;
    3027    protected $background_image='',$background_image_center=true,
    31     $backround_image_format='',$background_image_mix=100,
    32     $background_image_y=NULL, $background_image_x=NULL;
    33     private $doshadow=false, $shadow_width=4, $shadow_color='gray@0.5';
    34     public $footer;
    35 
     28        $backround_image_format='',$background_image_mix=100,
     29        $background_image_y=NULL, $background_image_x=NULL;
    3630
    3731    // Create a new instane of the combined graph
    38     function __construct($aWidth=NULL,$aHeight=NULL,$aCachedName='',$aTimeOut=0,$aInline=true) {
    39         $this->iWidth = $aWidth;
    40         $this->iHeight = $aHeight;
    41 
    42         // If the cached version exist just read it directly from the
    43         // cache, stream it back to browser and exit
    44         if( $aCachedName!='' && READ_CACHE && $aInline ) {
    45             $this->cache = new ImgStreamCache();
    46             $this->cache->SetTimeOut($aTimeOut);
    47             $image = new Image();
    48             if( $this->cache->GetAndStream($image,$aCachedName) ) {
    49                 exit();
    50             }
    51         }
    52         $this->inline = $aInline;
    53         $this->cache_name = $aCachedName;
    54 
    55         $this->title = new Text();
    56         $this->title->ParagraphAlign('center');
    57         $this->title->SetFont(FF_FONT2,FS_BOLD);
    58         $this->title->SetMargin(3);
    59         $this->title->SetAlign('center');
    60 
    61         $this->subtitle = new Text();
    62         $this->subtitle->ParagraphAlign('center');
    63         $this->subtitle->SetFont(FF_FONT1,FS_BOLD);
    64         $this->subtitle->SetMargin(3);
    65         $this->subtitle->SetAlign('center');
    66 
    67         $this->subsubtitle = new Text();
    68         $this->subsubtitle->ParagraphAlign('center');
    69         $this->subsubtitle->SetFont(FF_FONT1,FS_NORMAL);
    70         $this->subsubtitle->SetMargin(3);
    71         $this->subsubtitle->SetAlign('center');
    72 
    73         $this->footer = new Footer();
    74 
     32    function MGraph($aWidth=NULL,$aHeight=NULL) {
     33        $this->iWidth = $aWidth;
     34        $this->iHeight = $aHeight;
    7535    }
    7636
    7737    // Specify background fill color for the combined graph
    7838    function SetFillColor($aColor) {
    79         $this->iFillColor = $aColor;
     39        $this->iFillColor = $aColor;
    8040    }
    8141
    8242    // Add a frame around the combined graph
    8343    function SetFrame($aFlg,$aColor='black',$aWeight=1) {
    84         $this->iDoFrame = $aFlg;
    85         $this->iFrameColor = $aColor;
    86         $this->iFrameWeight = $aWeight;
    87     }
    88 
    89     // Specify a background image blend
     44        $this->iDoFrame = $aFlg;
     45        $this->iFrameColor = $aColor;
     46        $this->iFrameWeight = $aWeight;
     47    }
     48
     49    // Specify a background image blend   
    9050    function SetBackgroundImageMix($aMix) {
    91         $this->background_image_mix = $aMix ;
     51        $this->background_image_mix = $aMix ;
    9252    }
    9353
    9454    // Specify a background image
    9555    function SetBackgroundImage($aFileName,$aCenter_aX=NULL,$aY=NULL) {
    96         // Second argument can be either a boolean value or
    97         // a numeric
    98         $aCenter=TRUE;
    99         $aX=NULL;
    100 
    101         if( is_numeric($aCenter_aX) ) {
    102             $aX=$aCenter_aX;
    103         }
    104 
    105         // Get extension to determine image type
    106         $e = explode('.',$aFileName);
    107         if( !$e ) {
    108             JpGraphError::RaiseL(12002,$aFileName);
    109             //('Incorrect file name for MGraph::SetBackgroundImage() : '.$aFileName.' Must have a valid image extension (jpg,gif,png) when using autodetection of image type');
    110         }
    111 
    112         $valid_formats = array('png', 'jpg', 'gif');
    113         $aImgFormat = strtolower($e[count($e)-1]);
    114         if ($aImgFormat == 'jpeg')  {
    115             $aImgFormat = 'jpg';
    116         }
    117         elseif (!in_array($aImgFormat, $valid_formats) )  {
    118             JpGraphError::RaiseL(12003,$aImgFormat,$aFileName);
    119             //('Unknown file extension ($aImgFormat) in MGraph::SetBackgroundImage() for filename: '.$aFileName);
    120         }
    121 
    122         $this->background_image = $aFileName;
    123         $this->background_image_center=$aCenter;
    124         $this->background_image_format=$aImgFormat;
    125         $this->background_image_x = $aX;
    126         $this->background_image_y = $aY;
    127     }
     56        // Second argument can be either a boolean value or
     57        // a numeric
     58        $aCenter=TRUE;
     59        $aX=NULL;
     60
     61        if( $GLOBALS['gd2'] && !USE_TRUECOLOR ) {
     62            JpGraphError::RaiseL(12001);
     63//("You are using GD 2.x and are trying to use a background images on a non truecolor image. To use background images with GD 2.x you <b>must</b> enable truecolor by setting the USE_TRUECOLOR constant to TRUE. Due to a bug in GD 2.0.1 using any truetype fonts with truecolor images will result in very poor quality fonts.");
     64        }
     65        if( is_numeric($aCenter_aX) ) {
     66            $aX=$aCenter_aX;
     67        }
     68
     69        // Get extension to determine image type
     70        $e = explode('.',$aFileName);
     71        if( !$e ) {
     72            JpGraphError::RaiseL(12002,$aFileName);
     73//('Incorrect file name for MGraph::SetBackgroundImage() : '.$aFileName.' Must have a valid image extension (jpg,gif,png) when using autodetection of image type');
     74        }
     75       
     76        $valid_formats = array('png', 'jpg', 'gif');
     77        $aImgFormat = strtolower($e[count($e)-1]);
     78        if ($aImgFormat == 'jpeg')  {
     79            $aImgFormat = 'jpg';
     80        }
     81        elseif (!in_array($aImgFormat, $valid_formats) )  {
     82            JpGraphError::RaiseL(12003,$aImgFormat,$aFileName);
     83//('Unknown file extension ($aImgFormat) in MGraph::SetBackgroundImage() for filename: '.$aFileName);
     84        }   
     85
     86        $this->background_image = $aFileName;
     87        $this->background_image_center=$aCenter;
     88        $this->background_image_format=$aImgFormat;
     89        $this->background_image_x = $aX;
     90        $this->background_image_y = $aY;
     91    }
     92
     93
     94    // Private helper function for backgound image
     95    function _loadBkgImage($aFile='') {
     96        if( $aFile == '' )
     97            $aFile = $this->background_image;
     98
     99        // Remove case sensitivity and setup appropriate function to create image
     100        // Get file extension. This should be the LAST '.' separated part of the filename
     101        $e = explode('.',$aFile);
     102        $ext = strtolower($e[count($e)-1]);
     103        if ($ext == "jpeg")  {
     104            $ext = "jpg";
     105        }
     106       
     107        if( trim($ext) == '' )
     108            $ext = 'png';  // Assume PNG if no extension specified
     109
     110        $supported = imagetypes();
     111        if( ( $ext == 'jpg' && !($supported & IMG_JPG) ) ||
     112            ( $ext == 'gif' && !($supported & IMG_GIF) ) ||
     113            ( $ext == 'png' && !($supported & IMG_PNG) ) ) {
     114            JpGraphError::RaiseL(12004,$aFile);//('The image format of your background image ('.$aFile.') is not supported in your system configuration. ');
     115        }
     116
     117        if( $ext == "jpg" || $ext == "jpeg") {
     118            $f = "imagecreatefromjpeg";
     119            $ext = "jpg";
     120        }
     121        else {
     122            $f = "imagecreatefrom".$ext;
     123        }
     124
     125        $img = @$f($aFile);
     126        if( !$img ) {
     127            JpGraphError::RaiseL(12005,$aFile);
     128//(" Can't read background image: '".$aFile."'");   
     129        }
     130        return $img;
     131    }   
    128132
    129133    function _strokeBackgroundImage() {
    130         if( $this->background_image == '' ) return;
    131 
    132         $bkgimg = Graph::LoadBkgImage('',$this->background_image);
    133 
    134         // Background width & Heoght
    135         $bw = imagesx($bkgimg);
    136         $bh = imagesy($bkgimg);
    137 
    138         // Canvas width and height
    139         $cw = imagesx($this->img);
    140         $ch = imagesy($this->img);
    141 
    142         if( $this->doshadow ) {
    143             $cw -= $this->shadow_width;
    144             $ch -= $this->shadow_width;
    145         }
    146 
    147         if( $this->background_image_x === NULL || $this->background_image_y === NULL ) {
    148             if( $this->background_image_center ) {
    149                 // Center original image in the plot area
    150                 $x = round($cw/2-$bw/2); $y = round($ch/2-$bh/2);
    151             }
    152             else {
    153                 // Just copy the image from left corner, no resizing
    154                 $x=0; $y=0;
    155             }
    156         }
    157         else {
    158             $x = $this->background_image_x;
    159             $y = $this->background_image_y;
    160         }
    161         imagecopymerge($this->img,$bkgimg,$x,$y,0,0,$bw,$bh,$this->background_image_mix);
     134        if( $this->background_image == '' )
     135            return;
     136
     137        $bkgimg = $this->_loadBkgImage();
     138        // Background width & Heoght
     139        $bw = imagesx($bkgimg);
     140        $bh = imagesy($bkgimg);
     141        // Canvas width and height
     142        $cw = imagesx($this->img);
     143        $ch = imagesy($this->img);
     144
     145        if( $this->background_image_x === NULL || $this->background_image_y === NULL ) {
     146            if( $this->background_image_center ) {
     147                // Center original image in the plot area
     148                $x = round($cw/2-$bw/2); $y = round($ch/2-$bh/2);
     149            }
     150            else {
     151                // Just copy the image from left corner, no resizing
     152                $x=0; $y=0;
     153            }                   
     154        }
     155        else {
     156            $x = $this->background_image_x;
     157            $y = $this->background_image_y;
     158        }
     159        $this->_imageCp($bkgimg,$x,$y,0,0,$bw,$bh,$this->background_image_mix);
     160    }
     161
     162    function _imageCp($aSrcImg,$x,$y,$fx,$fy,$w,$h,$mix=100) {
     163        imagecopymerge($this->img,$aSrcImg,$x,$y,$fx,$fy,$w,$h,$mix);
     164    }
     165
     166    function _imageCreate($aWidth,$aHeight) {
     167        if( $aWidth <= 1 || $aHeight <= 1 ) {
     168            JpGraphError::RaiseL(12006,$aWidth,$aHeight);
     169//("Illegal sizes specified for width or height when creating an image, (width=$aWidth, height=$aHeight)");
     170        }
     171        if( @$GLOBALS['gd2']==true && USE_TRUECOLOR ) {
     172            $this->img = @imagecreatetruecolor($aWidth, $aHeight);
     173            if( $this->img < 1 ) {
     174                JpGraphError::RaiseL(12011);
     175// die("<b>JpGraph Error:</b> Can't create truecolor image. Check that you really have GD2 library installed.");
     176            }
     177            ImageAlphaBlending($this->img,true);
     178        } else {
     179            $this->img = @imagecreate($aWidth, $aHeight);       
     180            if( $this->img < 1 ) {
     181                JpGraphError::RaiseL(12012);
     182// die("<b>JpGraph Error:</b> Can't create image. Check that you really have the GD library installed.");
     183            }
     184        }
     185    }
     186
     187    function _polygon($p,$closed=FALSE) {
     188        if( $this->iLineWeight==0 ) return;
     189        $n=count($p);
     190        $oldx = $p[0];
     191        $oldy = $p[1];
     192        for( $i=2; $i < $n; $i+=2 ) {
     193            imageline($this->img,$oldx,$oldy,$p[$i],$p[$i+1],$this->iCurrentColor);
     194            $oldx = $p[$i];
     195            $oldy = $p[$i+1];
     196        }
     197        if( $closed ) {
     198            imageline($this->img,$p[$n*2-2],$p[$n*2-1],$p[0],$p[1],$this->iCurrentColor);
     199        }
     200    }
     201
     202    function _filledPolygon($pts) {
     203        $n=count($pts);
     204        for($i=0; $i < $n; ++$i)
     205            $pts[$i] = round($pts[$i]);
     206        imagefilledpolygon($this->img,$pts,count($pts)/2,$this->iCurrentColor);
     207    }
     208       
     209    function _rectangle($xl,$yu,$xr,$yl) {
     210        for($i=0; $i < $this->iLineWeight; ++$i )
     211            $this->_polygon(array($xl+$i,$yu+$i,$xr-$i,$yu+$i,
     212                                  $xr-$i,$yl-$i,$xl+$i,$yl-$i,
     213                                  $xl+$i,$yu+$i));
     214    }
     215       
     216    function _filledRectangle($xl,$yu,$xr,$yl) {
     217        $this->_filledPolygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl));
     218    }
     219
     220    function _setColor($aColor) {
     221        $this->iCurrentColor = $this->iRGB->Allocate($aColor);
    162222    }
    163223
    164224    function AddMix($aGraph,$x=0,$y=0,$mix=100,$fx=0,$fy=0,$w=0,$h=0) {
    165         $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h,$mix);
    166     }
    167 
     225        $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h,$mix);
     226    }
     227   
    168228    function Add($aGraph,$x=0,$y=0,$fx=0,$fy=0,$w=0,$h=0) {
    169         $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h);
     229        $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h);
    170230    }
    171231
    172232    function _gdImgHandle($agdCanvas,$x,$y,$fx=0,$fy=0,$w=0,$h=0,$mix=100) {
    173         if( $w == 0 ) {
    174             $w = @imagesx($agdCanvas);
    175         }
    176         if( $w === NULL ) {
    177             JpGraphError::RaiseL(12007);
    178             //('Argument to MGraph::Add() is not a valid GD image handle.');
    179             return;
    180         }
    181         if( $h == 0 ) {
    182             $h = @imagesy($agdCanvas);
    183         }
    184         $this->iGraphs[$this->iCnt++] = array($agdCanvas,$x,$y,$fx,$fy,$w,$h,$mix);
     233        if( $w == 0 )  $w = @imagesx($agdCanvas);
     234        if( $w === NULL ) {
     235            JpGraphError::RaiseL(12007);
     236//('Argument to MGraph::Add() is not a valid GD image handle.');
     237            return;
     238        }
     239        if( $h == 0 )  $h = @imagesy($agdCanvas);
     240        $this->iGraphs[$this->iCnt++] = array($agdCanvas,$x,$y,$fx,$fy,$w,$h,$mix);
    185241    }
    186242
    187243    function SetMargin($lm,$rm,$tm,$bm) {
    188         $this->lm = $lm;
    189         $this->rm = $rm;
    190         $this->tm = $tm;
    191         $this->bm = $bm;
     244        $this->lm = $lm;
     245        $this->rm = $rm;
     246        $this->tm = $tm;
     247        $this->bm = $bm;
    192248    }
    193249
    194250    function SetExpired($aFlg=true) {
    195         $this->expired = $aFlg;
     251        $this->expired = $aFlg;
     252    }
     253
     254    // Generate image header
     255    function Headers() {
     256       
     257        // In case we are running from the command line with the client version of
     258        // PHP we can't send any headers.
     259        $sapi = php_sapi_name();
     260        if( $sapi == 'cli' )
     261            return;
     262       
     263        if( headers_sent() ) {
     264           
     265            echo "<table border=1><tr><td><font color=darkred size=4><b>JpGraph Error:</b>
     266HTTP headers have already been sent.</font></td></tr><tr><td><b>Explanation:</b><br>HTTP headers have already been sent back to the browser indicating the data as text before the library got a chance to send it's image HTTP header to this browser. This makes it impossible for the library to send back image data to the browser (since that would be interpretated as text by the browser and show up as junk text).<p>Most likely you have some text in your script before the call to <i>Graph::Stroke()</i>. If this texts gets sent back to the browser the browser will assume that all data is plain text. Look for any text, even spaces and newlines, that might have been sent back to the browser. <p>For example it is a common mistake to leave a blank line before the opening \"<b>&lt;?php</b>\".</td></tr></table>";
     267
     268        die();
     269
     270        }       
     271       
     272        if ($this->expired) {
     273            header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
     274            header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
     275            header("Cache-Control: no-cache, must-revalidate");
     276            header("Pragma: no-cache");
     277        }
     278        header("Content-type: image/$this->img_format");
    196279    }
    197280
    198281    function SetImgFormat($aFormat,$aQuality=75) {
    199         $this->image_format = $aFormat;
    200         $this->image_quality = $aQuality;
    201     }
    202 
    203     // Set the shadow around the whole image
    204     function SetShadow($aShowShadow=true,$aShadowWidth=4,$aShadowColor='gray@0.3') {
    205         $this->doshadow = $aShowShadow;
    206         $this->shadow_color = $aShadowColor;
    207         $this->shadow_width = $aShadowWidth;
    208         $this->footer->iBottomMargin += $aShadowWidth;
    209         $this->footer->iRightMargin += $aShadowWidth;
    210     }
    211 
    212     function StrokeTitle($image,$w,$h) {
    213         // Stroke title
    214         if( $this->title->t !== '' ) {
    215 
    216             $margin = 3;
    217 
    218             $y = $this->title->margin;
    219             if( $this->title->halign == 'center' ) {
    220                 $this->title->Center(0,$w,$y);
    221             }
    222             elseif( $this->title->halign == 'left' ) {
    223                 $this->title->SetPos($this->title->margin+2,$y);
    224             }
    225             elseif( $this->title->halign == 'right' ) {
    226                 $indent = 0;
    227                 if( $this->doshadow ) {
    228                     $indent = $this->shadow_width+2;
    229                 }
    230                 $this->title->SetPos($w-$this->title->margin-$indent,$y,'right');
    231             }
    232             $this->title->Stroke($image);
    233 
    234             // ... and subtitle
    235             $y += $this->title->GetTextHeight($image) + $margin + $this->subtitle->margin;
    236             if( $this->subtitle->halign == 'center' ) {
    237                 $this->subtitle->Center(0,$w,$y);
    238             }
    239             elseif( $this->subtitle->halign == 'left' ) {
    240                 $this->subtitle->SetPos($this->subtitle->margin+2,$y);
    241             }
    242             elseif( $this->subtitle->halign == 'right' ) {
    243                 $indent = 0;
    244                 if( $this->doshadow ) {
    245                     $indent = $this->shadow_width+2;
    246                 }
    247                 $this->subtitle->SetPos($this->img->width-$this->subtitle->margin-$indent,$y,'right');
    248             }
    249             $this->subtitle->Stroke($image);
    250 
    251             // ... and subsubtitle
    252             $y += $this->subtitle->GetTextHeight($image) + $margin + $this->subsubtitle->margin;
    253             if( $this->subsubtitle->halign == 'center' ) {
    254                 $this->subsubtitle->Center(0,$w,$y);
    255             }
    256             elseif( $this->subsubtitle->halign == 'left' ) {
    257                 $this->subsubtitle->SetPos($this->subsubtitle->margin+2,$y);
    258             }
    259             elseif( $this->subsubtitle->halign == 'right' ) {
    260                 $indent = 0;
    261                 if( $this->doshadow ) {
    262                     $indent = $this->shadow_width+2;
    263                 }
    264                 $this->subsubtitle->SetPos($w-$this->subsubtitle->margin-$indent,$y,'right');
    265             }
    266             $this->subsubtitle->Stroke($image);
    267 
    268         }
     282        $this->image_quality = $aQuality;
     283        $aFormat = strtolower($aFormat);
     284        $tst = true;
     285        $supported = imagetypes();
     286        if( $aFormat=="auto" ) {
     287            if( $supported & IMG_PNG )
     288                $this->img_format="png";
     289            elseif( $supported & IMG_JPG )
     290                $this->img_format="jpeg";
     291            elseif( $supported & IMG_GIF )
     292                $this->img_format="gif";
     293            else
     294                JpGraphError::RaiseL(12008);
     295//(" Your PHP (and GD-lib) installation does not appear to support any known graphic formats.".
     296            return true;
     297        }
     298        else {
     299            if( $aFormat=="jpeg" || $aFormat=="png" || $aFormat=="gif" ) {
     300                if( $aFormat=="jpeg" && !($supported & IMG_JPG) )
     301                    $tst=false;
     302                elseif( $aFormat=="png" && !($supported & IMG_PNG) )
     303                    $tst=false;
     304                elseif( $aFormat=="gif" && !($supported & IMG_GIF) )   
     305                    $tst=false;
     306                else {
     307                    $this->img_format=$aFormat;
     308                    return true;
     309                }
     310            }
     311            else
     312                $tst=false;
     313            if( !$tst )
     314                JpGraphError::RaiseL(12009,$aFormat);
     315//(" Your PHP installation does not support the chosen graphic format: $aFormat");
     316        }
     317    }
     318
     319    // Stream image to browser or to file
     320    function Stream($aFile="") {
     321        $func="image".$this->img_format;
     322        if( $this->img_format=="jpeg" && $this->image_quality != null ) {
     323            $res = @$func($this->img,$aFile,$this->image_quality);
     324        }
     325        else {
     326            if( $aFile != "" ) {
     327                $res = @$func($this->img,$aFile);
     328            }
     329            else
     330                $res = @$func($this->img);
     331        }
     332        if( !$res )
     333            JpGraphError::RaiseL(12010,$aFile);
     334//("Can't create or stream image to file $aFile Check that PHP has enough permission to write a file to the current directory.");
    269335    }
    270336
    271337    function Stroke($aFileName='') {
    272         // Find out the necessary size for the container image
    273         $w=0; $h=0;
    274         for($i=0; $i < $this->iCnt; ++$i ) {
    275             $maxw = $this->iGraphs[$i][1]+$this->iGraphs[$i][5];
    276             $maxh = $this->iGraphs[$i][2]+$this->iGraphs[$i][6];
    277             $w = max( $w, $maxw );
    278             $h = max( $h, $maxh );
    279         }
    280         $w += $this->lm+$this->rm;
    281         $h += $this->tm+$this->bm;
    282 
    283         // User specified width,height overrides
    284         if( $this->iWidth !== NULL && $this->iWidth !== 0 ) $w = $this->iWidth;
    285         if( $this->iHeight!== NULL && $this->iHeight !== 0) $h = $this->iHeight;
    286 
    287         if( $this->doshadow ) {
    288             $w += $this->shadow_width;
    289             $h += $this->shadow_width;
    290         }
    291 
    292         $image = new Image($w,$h);
    293         $image->SetImgFormat( $this->image_format,$this->image_quality);
    294 
    295         if( $this->doshadow ) {
    296             $image->SetColor($this->iFrameColor);
    297             $image->ShadowRectangle(0,0,$w-1,$h-1,$this->iFillColor,$this->shadow_width,$this->shadow_color);
    298             $w -= $this->shadow_width;
    299             $h -= $this->shadow_width;
    300         }
    301         else {
    302             $image->SetColor($this->iFillColor);
    303             $image->FilledRectangle(0,0,$w-1,$h-1);
    304         }
    305         $image->SetExpired($this->expired);
    306 
    307         $this->img = $image->img;
    308         $this->_strokeBackgroundImage();
    309 
    310         if( $this->iDoFrame && ! $this->doshadow ) {
    311            $image->SetColor($this->iFrameColor);
    312            $image->SetLineWeight($this->iFrameWeight);
    313            $image->Rectangle(0,0,$w-1,$h-1);
    314         }
    315 
    316         // Copy all sub graphs to the container
    317         for($i=0; $i < $this->iCnt; ++$i ) {
    318             $image->CopyMerge($this->iGraphs[$i][0],
    319                             $this->iGraphs[$i][1]+$this->lm,$this->iGraphs[$i][2]+$this->tm,
    320                             $this->iGraphs[$i][3],$this->iGraphs[$i][4],
    321                             $this->iGraphs[$i][5],$this->iGraphs[$i][6],
    322                             -1,-1, /* Full from width and height */
    323                             $this->iGraphs[$i][7]);
    324 
    325 
    326         }
    327 
    328         $this->StrokeTitle($image,$w,$h);
    329         $this->footer->Stroke($image);
    330 
    331         // Output image
    332         if( $aFileName == _IMG_HANDLER ) {
    333             return $image->img;
    334         }
    335         else {
    336             //Finally stream the generated picture
    337             $this->cache = new ImgStreamCache();
    338             $this->cache->PutAndStream($image,$this->cache_name,$this->inline,$aFileName);
    339         }
     338        // Find out the necessary size for the container image
     339        $w=0; $h=0;
     340        for($i=0; $i < $this->iCnt; ++$i ) {
     341            $maxw = $this->iGraphs[$i][1]+$this->iGraphs[$i][5];
     342            $maxh = $this->iGraphs[$i][2]+$this->iGraphs[$i][6];
     343            $w = max( $w, $maxw );
     344            $h = max( $h, $maxh );
     345        }
     346        $w += $this->lm+$this->rm;
     347        $h += $this->tm+$this->bm;
     348
     349        // User specified width,height overrides
     350        if( $this->iWidth !== NULL ) $w = $this->iWidth;
     351        if( $this->iHeight!== NULL ) $h = $this->iHeight;
     352
     353        $this->_imageCreate($w,$h);
     354        $this->iRGB = new RGB($this->img);
     355
     356        $this->_setcolor($this->iFillColor);
     357        $this->_filledRectangle(0,0,$w-1,$h-1);
     358
     359        $this->_strokeBackgroundImage();
     360
     361        if( $this->iDoFrame ) {
     362            $this->_setColor($this->iFrameColor);
     363            $this->iLineWeight=$this->iFrameWeight;
     364            $this->_rectangle(0,0,$w-1,$h-1);
     365        }
     366
     367        // Copy all sub graphs to the container
     368        for($i=0; $i < $this->iCnt; ++$i ) {
     369            $this->_imageCp($this->iGraphs[$i][0],
     370                            $this->iGraphs[$i][1]+$this->lm,$this->iGraphs[$i][2]+$this->tm,
     371                            $this->iGraphs[$i][3],$this->iGraphs[$i][4],
     372                            $this->iGraphs[$i][5],$this->iGraphs[$i][6],
     373                            $this->iGraphs[$i][7]);
     374        }
     375
     376        // Output image
     377        if( $aFileName == _IMG_HANDLER ) {
     378            return $this->img;
     379        }
     380        else {
     381            if( $aFileName != '' ) {
     382                $this->Stream($aFileName);
     383            }
     384            else {
     385                $this->Headers();
     386                $this->Stream();
     387            }
     388        }
    340389    }
    341390}
    342391
    343 // EOF
    344 
    345392?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_pie.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_PIE.PHP
    4  // Description: Pie plot extension for JpGraph
    5  // Created:     2001-02-14
    6  // Ver:         $Id: jpgraph_pie.php 1926 2010-01-11 16:33:07Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_PIE.PHP
     4// Description: Pie plot extension for JpGraph
     5// Created:     2001-02-14
     6// Ver:         $Id: jpgraph_pie.php 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212
     
    2424class PiePlot {
    2525    public $posx=0.5,$posy=0.5;
    26     public $is_using_plot_theme = false;
    27     public $theme="earth";
    28     protected $use_plot_theme_colors = false;
    2926    protected $radius=0.3;
    3027    protected $explode_radius=array(),$explode_all=false,$explode_r=20;
    3128    protected $labels=null, $legends=null;
    3229    protected $csimtargets=null,$csimwintargets=null;  // Array of targets for CSIM
    33     protected $csimareas='';  // Generated CSIM text
    34     protected $csimalts=null;  // ALT tags for corresponding target
     30    protected $csimareas='';            // Generated CSIM text 
     31    protected $csimalts=null;           // ALT tags for corresponding target
    3532    protected $data=null;
    3633    public $title;
     
    3936    protected $legend_margin=6,$show_labels=true;
    4037    protected $themearr = array(
    41  "earth"  => array(136,34,40,45,46,62,63,134,74,10,120,136,141,168,180,77,209,218,346,395,89,430),
    42  "pastel" => array(27,415,128,59,66,79,105,110,42,147,152,230,236,240,331,337,405,38),
    43  "water"  => array(8,370,24,40,335,56,213,237,268,14,326,387,10,388),
    44  "sand"   => array(27,168,34,170,19,50,65,72,131,209,46,393));
     38        "earth"         => array(136,34,40,45,46,62,63,134,74,10,120,136,141,168,180,77,209,218,346,395,89,430),
     39        "pastel" => array(27,415,128,59,66,79,105,110,42,147,152,230,236,240,331,337,405,38),
     40        "water"  => array(8,370,24,40,335,56,213,237,268,14,326,387,10,388),
     41        "sand"   => array(27,168,34,170,19,50,65,72,131,209,46,393));
     42    protected $theme="earth";
    4543    protected $setslicecolors=array();
    4644    protected $labeltype=0; // Default to percentage
     
    5654    protected $iGuideLineCurve = false,$iGuideVFactor=1.4,$iGuideLineRFactor=0.8;
    5755    protected $la = array(); // Holds the exact angle for each label
    58 
    59     //---------------
    60     // CONSTRUCTOR
    61     function __construct($data) {
    62         $this->data = array_reverse($data);
    63         $this->title = new Text("");
    64         $this->title->SetFont(FF_DEFAULT,FS_BOLD);
    65         $this->value = new DisplayValue();
    66         $this->value->Show();
    67         $this->value->SetFormat('%.1f%%');
    68         $this->guideline = new LineProperty();
    69     }
    70 
    71     //---------------
    72     // PUBLIC METHODS
     56       
     57//---------------
     58// CONSTRUCTOR
     59    function PiePlot($data) {
     60        $this->data = array_reverse($data);
     61        $this->title = new Text("");
     62        $this->title->SetFont(FF_FONT1,FS_BOLD);
     63        $this->value = new DisplayValue();
     64        $this->value->Show();
     65        $this->value->SetFormat('%.1f%%');
     66        $this->guideline = new LineProperty();
     67    }
     68
     69//---------------
     70// PUBLIC METHODS       
    7371    function SetCenter($x,$y=0.5) {
    74         $this->posx = $x;
    75         $this->posy = $y;
     72        $this->posx = $x;
     73        $this->posy = $y;
    7674    }
    7775
    7876    // Enable guideline and set drwaing policy
    7977    function SetGuideLines($aFlg=true,$aCurved=true,$aAlways=false) {
    80         $this->guideline->Show($aFlg);
    81         $this->iShowGuideLineForSingle = $aAlways;
    82         $this->iGuideLineCurve = $aCurved;
     78        $this->guideline->Show($aFlg);
     79        $this->iShowGuideLineForSingle = $aAlways;
     80        $this->iGuideLineCurve = $aCurved;
    8381    }
    8482
    8583    // Adjuste the distance between labels and labels and pie
    8684    function SetGuideLinesAdjust($aVFactor,$aRFactor=0.8) {
    87         $this->iGuideVFactor=$aVFactor;
    88         $this->iGuideLineRFactor=$aRFactor;
     85        $this->iGuideVFactor=$aVFactor;
     86        $this->iGuideLineRFactor=$aRFactor;
    8987    }
    9088
    9189    function SetColor($aColor) {
    92         $this->color = $aColor;
    93     }
    94 
     90        $this->color = $aColor;
     91    }
     92       
    9593    function SetSliceColors($aColors) {
    96         $this->setslicecolors = $aColors;
    97     }
    98 
     94        $this->setslicecolors = $aColors;
     95    }
     96       
    9997    function SetShadow($aColor='darkgray',$aDropWidth=4) {
    100         $this->ishadowcolor = $aColor;
    101         $this->ishadowdrop = $aDropWidth;
     98        $this->ishadowcolor = $aColor;
     99        $this->ishadowdrop = $aDropWidth;
    102100    }
    103101
    104102    function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') {
    105         $this->csimtargets=array_reverse($aTargets);
    106         if( is_array($aWinTargets) )
    107         $this->csimwintargets=array_reverse($aWinTargets);
    108         if( is_array($aAlts) )
    109         $this->csimalts=array_reverse($aAlts);
    110     }
    111 
     103        $this->csimtargets=array_reverse($aTargets);
     104        if( is_array($aWinTargets) )
     105            $this->csimwintargets=array_reverse($aWinTargets);
     106        if( is_array($aAlts) )
     107            $this->csimalts=array_reverse($aAlts);
     108    }
     109       
    112110    function GetCSIMareas() {
    113         return $this->csimareas;
    114     }
    115 
    116     function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {
     111        return $this->csimareas;
     112    }
     113
     114    function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { 
    117115        //Slice number, ellipse centre (x,y), height, width, start angle, end angle
    118         while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
    119         while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
    120 
    121         $sa = 2*M_PI - $sa;
    122         $ea = 2*M_PI - $ea;
    123 
    124         // Special case when we have only one slice since then both start and end
    125         // angle will be == 0
    126         if( abs($sa - $ea) < 0.0001 ) {
    127             $sa=2*M_PI; $ea=0;
    128         }
    129 
    130         //add coordinates of the centre to the map
    131         $xc = floor($xc);$yc=floor($yc);
    132         $coords = "$xc, $yc";
    133 
    134         //add coordinates of the first point on the arc to the map
    135         $xp = floor(($radius*cos($ea))+$xc);
    136         $yp = floor($yc-$radius*sin($ea));
    137         $coords.= ", $xp, $yp";
    138 
    139         //add coordinates every 0.2 radians
    140         $a=$ea+0.2;
    141 
    142         // If we cross the 360-limit with a slice we need to handle
    143         // the fact that end angle is smaller than start
    144         if( $sa < $ea ) {
    145             while ($a <= 2*M_PI) {
    146                 $xp = floor($radius*cos($a)+$xc);
    147                 $yp = floor($yc-$radius*sin($a));
    148                 $coords.= ", $xp, $yp";
    149                 $a += 0.2;
    150             }
    151             $a -= 2*M_PI;
    152         }
    153 
    154 
    155         while ($a < $sa) {
    156             $xp = floor($radius*cos($a)+$xc);
    157             $yp = floor($yc-$radius*sin($a));
    158             $coords.= ", $xp, $yp";
    159             $a += 0.2;
    160         }
    161 
    162         //Add the last point on the arc
    163         $xp = floor($radius*cos($sa)+$xc);
    164         $yp = floor($yc-$radius*sin($sa));
    165         $coords.= ", $xp, $yp";
    166         if( !empty($this->csimtargets[$i]) ) {
    167             $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtargets[$i]."\"";
    168             $tmp="";
    169             if( !empty($this->csimwintargets[$i]) ) {
    170                 $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
    171             }
    172             if( !empty($this->csimalts[$i]) ) {
    173                 $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
    174                 $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
    175             }
    176             $this->csimareas .= " />\n";
    177         }
    178     }
    179 
    180 
     116        while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
     117        while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
     118
     119        $sa = 2*M_PI - $sa;
     120        $ea = 2*M_PI - $ea;
     121
     122        // Special case when we have only one slice since then both start and end
     123        // angle will be == 0
     124        if( abs($sa - $ea) < 0.0001 ) {
     125            $sa=2*M_PI; $ea=0;
     126        }
     127
     128        //add coordinates of the centre to the map
     129        $xc = floor($xc);$yc=floor($yc);
     130        $coords = "$xc, $yc";
     131
     132        //add coordinates of the first point on the arc to the map
     133        $xp = floor(($radius*cos($ea))+$xc);
     134        $yp = floor($yc-$radius*sin($ea));
     135        $coords.= ", $xp, $yp";
     136       
     137        //add coordinates every 0.2 radians
     138        $a=$ea+0.2;
     139
     140        // If we cross the 360-limit with a slice we need to handle
     141        // the fact that end angle is smaller than start
     142        if( $sa < $ea ) {
     143            while ($a <= 2*M_PI) {
     144                $xp = floor($radius*cos($a)+$xc);
     145                $yp = floor($yc-$radius*sin($a));
     146                $coords.= ", $xp, $yp";
     147                $a += 0.2;
     148            }
     149            $a -= 2*M_PI;
     150        }
     151
     152
     153        while ($a < $sa) {
     154            $xp = floor($radius*cos($a)+$xc);
     155            $yp = floor($yc-$radius*sin($a));
     156            $coords.= ", $xp, $yp";
     157            $a += 0.2;
     158        }
     159               
     160        //Add the last point on the arc
     161        $xp = floor($radius*cos($sa)+$xc);
     162        $yp = floor($yc-$radius*sin($sa));
     163        $coords.= ", $xp, $yp";
     164        if( !empty($this->csimtargets[$i]) ) {
     165            $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtargets[$i]."\"";
     166            $tmp="";
     167            if( !empty($this->csimwintargets[$i]) ) {
     168                $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
     169            }
     170            if( !empty($this->csimalts[$i]) ) {
     171                $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
     172                $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
     173            }
     174            $this->csimareas .= " />\n";
     175        }
     176    }
     177
     178       
    181179    function SetTheme($aTheme) {
    182 //        JpGraphError::RaiseL(15012,$aTheme);
    183 //        return;
    184 
    185         if( in_array($aTheme,array_keys($this->themearr)) ) {
    186             $this->theme = $aTheme;
    187             $this->is_using_plot_theme = true;
    188         } else {
    189             JpGraphError::RaiseL(15001,$aTheme);//("PiePLot::SetTheme() Unknown theme: $aTheme");
    190         }
    191     }
    192 
     180        if( in_array($aTheme,array_keys($this->themearr)) )
     181            $this->theme = $aTheme;
     182        else
     183            JpGraphError::RaiseL(15001,$aTheme);//("PiePLot::SetTheme() Unknown theme: $aTheme");
     184    }
     185       
    193186    function ExplodeSlice($e,$radius=20) {
    194         if( ! is_integer($e) )
    195         JpGraphError::RaiseL(15002);//('Argument to PiePlot::ExplodeSlice() must be an integer');
    196         $this->explode_radius[$e]=$radius;
     187        if( ! is_integer($e) )
     188            JpGraphError::RaiseL(15002);//('Argument to PiePlot::ExplodeSlice() must be an integer');
     189        $this->explode_radius[$e]=$radius;
    197190    }
    198191
    199192    function ExplodeAll($radius=20) {
    200         $this->explode_all=true;
    201         $this->explode_r = $radius;
     193        $this->explode_all=true;
     194        $this->explode_r = $radius;
    202195    }
    203196
    204197    function Explode($aExplodeArr) {
    205         if( !is_array($aExplodeArr) ) {
    206             JpGraphError::RaiseL(15003);
    207             //("Argument to PiePlot::Explode() must be an array with integer distances.");
    208         }
    209         $this->explode_radius = $aExplodeArr;
     198        if( !is_array($aExplodeArr) ) {
     199            JpGraphError::RaiseL(15003);
     200//("Argument to PiePlot::Explode() must be an array with integer distances.");
     201        }
     202        $this->explode_radius = $aExplodeArr;
    210203    }
    211204
    212205    function SetStartAngle($aStart) {
    213         if( $aStart < 0 || $aStart > 360 ) {
    214             JpGraphError::RaiseL(15004);//('Slice start angle must be between 0 and 360 degrees.');
    215         }
    216         if( $aStart == 0 ) {
    217             $this->startangle = 0;
    218         }
    219         else {
    220             $this->startangle = 360-$aStart;
    221             $this->startangle *= M_PI/180;
    222         }
    223     }
    224 
     206        if( $aStart < 0 || $aStart > 360 ) {
     207            JpGraphError::RaiseL(15004);//('Slice start angle must be between 0 and 360 degrees.');
     208        }
     209        $this->startangle = 360-$aStart;
     210        $this->startangle *= M_PI/180;
     211    }
     212       
     213    function SetFont($family,$style=FS_NORMAL,$size=10) {
     214        JpGraphError::RaiseL(15005);//('PiePlot::SetFont() is deprecated. Use PiePlot->value->SetFont() instead.');
     215    }
     216       
    225217    // Size in percentage
    226218    function SetSize($aSize) {
    227         if( ($aSize>0 && $aSize<=0.5) || ($aSize>10 && $aSize<1000) )
    228         $this->radius = $aSize;
    229         else
    230         JpGraphError::RaiseL(15006);
    231         //("PiePlot::SetSize() Radius for pie must either be specified as a fraction [0, 0.5] of the size of the image or as an absolute size in pixels  in the range [10, 1000]");
    232     }
    233 
     219        if( ($aSize>0 && $aSize<=0.5) || ($aSize>10 && $aSize<1000) )
     220            $this->radius = $aSize;
     221        else
     222            JpGraphError::RaiseL(15006);
     223//("PiePlot::SetSize() Radius for pie must either be specified as a fraction [0, 0.5] of the size of the image or as an absolute size in pixels  in the range [10, 1000]");
     224    }
     225       
     226    function SetFontColor($aColor) {
     227        JpGraphError::RaiseL(15007);
     228//('PiePlot::SetFontColor() is deprecated. Use PiePlot->value->SetColor() instead.');
     229    }
     230       
    234231    // Set label arrays
    235232    function SetLegends($aLegend) {
    236         $this->legends = $aLegend;
    237     }
    238 
    239     // Set text labels for slices
     233        $this->legends = $aLegend;
     234    }
     235
     236    // Set text labels for slices 
    240237    function SetLabels($aLabels,$aLblPosAdj="auto") {
    241         $this->labels = array_reverse($aLabels);
    242         $this->ilabelposadj=$aLblPosAdj;
     238        $this->labels = array_reverse($aLabels);
     239        $this->ilabelposadj=$aLblPosAdj;
    243240    }
    244241
    245242    function SetLabelPos($aLblPosAdj) {
    246         $this->ilabelposadj=$aLblPosAdj;
    247     }
    248 
     243        $this->ilabelposadj=$aLblPosAdj;
     244    }
     245       
    249246    // Should we display actual value or percentage?
    250     function SetLabelType($aType) {
    251         if( $aType < 0 || $aType > 2 )
    252                 JpGraphError::RaiseL(15008,$aType);
    253                 //("PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not $t).");
    254         $this->labeltype = $aType;
    255     }
    256 
    257     // Deprecated.
     247    function SetLabelType($t) {
     248        if( $t < 0 || $t > 2 )
     249            JpGraphError::RaiseL(15008,$t);
     250//("PiePlot::SetLabelType() Type for pie plots must be 0 or 1 (not $t).");
     251        $this->labeltype=$t;
     252    }
     253
     254    // Deprecated. 
    258255    function SetValueType($aType) {
    259         $this->SetLabelType($aType);
     256        $this->SetLabelType($aType);
    260257    }
    261258
    262259    // Should the circle around a pie plot be displayed
    263260    function ShowBorder($exterior=true,$interior=true) {
    264         $this->pie_border = $exterior;
    265         $this->pie_interior_border = $interior;
    266     }
    267 
     261        $this->pie_border = $exterior;
     262        $this->pie_interior_border = $interior;
     263    }
     264       
    268265    // Setup the legends
    269266    function Legend($graph) {
    270         $colors = array_keys($graph->img->rgb->rgb_table);
    271         sort($colors);
    272         $ta=$this->themearr[$this->theme];
    273         $n = count($this->data);
    274 
    275         if( $this->setslicecolors==null ) {
    276             $numcolors=count($ta);
    277             if( class_exists('PiePlot3D',false) && ($this instanceof PiePlot3D) ) {
    278                 $ta = array_reverse(array_slice($ta,0,$n));
    279             }
    280         }
    281         else {
    282             $this->setslicecolors = array_slice($this->setslicecolors,0,$n);
    283             $numcolors=count($this->setslicecolors);
    284             if( $graph->pieaa && !($this instanceof PiePlot3D) ) {
    285                 $this->setslicecolors = array_reverse($this->setslicecolors);
    286             }
    287         }
    288 
    289         $sum=0;
    290         for($i=0; $i < $n; ++$i)
    291             $sum += $this->data[$i];
    292 
    293         // Bail out with error if the sum is 0
    294         if( $sum==0 )
    295         JpGraphError::RaiseL(15009);//("Illegal pie plot. Sum of all data is zero for Pie!");
    296 
    297         // Make sure we don't plot more values than data points
    298         // (in case the user added more legends than data points)
    299         $legendsCount = is_array($this->legends) ? count($this->legends) : 0;
    300         $n = min($legendsCount,count($this->data));
    301         if( $this->legends != "" ) {
    302             $this->legends = array_reverse(array_slice($this->legends,0,$n));
    303         }
    304         for( $i=$n-1; $i >= 0; --$i ) {
    305             $l = $this->legends[$i];
    306             // Replace possible format with actual values
    307             $count = is_array($this->csimalts) ? count($this->csimalts) : 0;
    308             if( $count > $i ) {
    309                 $fmt = $this->csimalts[$i];
    310             }
    311             else {
    312                 $fmt = "%d"; // Deafult Alt if no other has been specified
    313             }
    314             if( $this->labeltype==0 ) {
    315                 $l = sprintf($l,100*$this->data[$i]/$sum);
    316                 $alt = sprintf($fmt,$this->data[$i]);
    317 
    318             }
    319             elseif( $this->labeltype == 1)  {
    320                 $l = sprintf($l,$this->data[$i]);
    321                 $alt = sprintf($fmt,$this->data[$i]);
    322 
    323             }
    324             else {
    325                 $l = sprintf($l,$this->adjusted_data[$i]);
    326                 $alt = sprintf($fmt,$this->adjusted_data[$i]);
    327             }
    328 
    329             if( empty($this->csimwintargets[$i]) ) {
    330                 $wintarg = '';
    331             }
    332             else {
    333                 $wintarg = $this->csimwintargets[$i];
    334             }
    335 
    336             if( $this->setslicecolors==null ) {
    337                 $graph->legend->Add($l,$colors[$ta[$i%$numcolors]],"",0,$this->csimtargets[$i],$alt,$wintarg);
    338             }
    339             else {
    340                 $graph->legend->Add($l,$this->setslicecolors[$i%$numcolors],"",0,$this->csimtargets[$i],$alt,$wintarg);
    341             }
    342         }
    343     }
    344 
     267        $colors = array_keys($graph->img->rgb->rgb_table);
     268        sort($colors); 
     269        $ta=$this->themearr[$this->theme];     
     270        $n = count($this->data);
     271
     272        if( $this->setslicecolors==null ) {
     273            $numcolors=count($ta);
     274            if( class_exists('PiePlot3D',false) && ($this instanceof PiePlot3D) ) {
     275                $ta = array_reverse(array_slice($ta,0,$n));
     276            }
     277        }
     278        else {
     279            $this->setslicecolors = array_slice($this->setslicecolors,0,$n);
     280            $numcolors=count($this->setslicecolors);
     281            if( $graph->pieaa && !($this instanceof PiePlot3D) ) {
     282                $this->setslicecolors = array_reverse($this->setslicecolors);
     283            }
     284        }
     285               
     286        $sum=0;
     287        for($i=0; $i < $n; ++$i)
     288            $sum += $this->data[$i];
     289
     290        // Bail out with error if the sum is 0
     291        if( $sum==0 )
     292            JpGraphError::RaiseL(15009);//("Illegal pie plot. Sum of all data is zero for Pie!");
     293
     294        // Make sure we don't plot more values than data points
     295        // (in case the user added more legends than data points)
     296        $n = min(count($this->legends),count($this->data));
     297        if( $this->legends != "" ) {
     298            $this->legends = array_reverse(array_slice($this->legends,0,$n));
     299        }
     300        for( $i=$n-1; $i >= 0; --$i ) {
     301            $l = $this->legends[$i];
     302            // Replace possible format with actual values
     303            if( count($this->csimalts) > $i ) {
     304                $fmt = $this->csimalts[$i];
     305            }
     306            else {
     307                $fmt = "%d"; // Deafult Alt if no other has been specified
     308            }
     309            if( $this->labeltype==0 ) {
     310                $l = sprintf($l,100*$this->data[$i]/$sum);
     311                $alt = sprintf($fmt,$this->data[$i]);
     312               
     313            }
     314            elseif( $this->labeltype == 1)  {
     315                $l = sprintf($l,$this->data[$i]);
     316                $alt = sprintf($fmt,$this->data[$i]);
     317               
     318            }
     319            else {
     320                $l = sprintf($l,$this->adjusted_data[$i]);
     321                $alt = sprintf($fmt,$this->adjusted_data[$i]);
     322            }
     323
     324            if( empty($this->csimwintargets[$i]) ) {
     325                $wintarg = '';
     326            }
     327            else {
     328                $wintarg = $this->csimwintargets[$i];
     329            }
     330
     331            if( $this->setslicecolors==null ) {
     332                $graph->legend->Add($l,$colors[$ta[$i%$numcolors]],"",0,$this->csimtargets[$i],$alt,$wintarg);
     333            }
     334            else {
     335                $graph->legend->Add($l,$this->setslicecolors[$i%$numcolors],"",0,$this->csimtargets[$i],$alt,$wintarg);
     336            }
     337        }
     338    }
     339       
    345340    // Adjust the rounded percetage value so that the sum of
    346341    // of the pie slices are always 100%
    347342    // Using the Hare/Niemeyer method
    348343    function AdjPercentage($aData,$aPrec=0) {
    349         $mul=100;
    350         if( $aPrec > 0 && $aPrec < 3 ) {
    351             if( $aPrec == 1 )
    352             $mul=1000;
    353             else
    354             $mul=10000;
    355         }
    356 
    357         $tmp = array();
    358         $result = array();
    359         $quote_sum=0;
    360         $n = count($aData) ;
    361         for( $i=0, $sum=0; $i < $n; ++$i )
    362         $sum+=$aData[$i];
    363         foreach($aData as $index => $value) {
    364             $tmp_percentage=$value/$sum*$mul;
    365             $result[$index]=floor($tmp_percentage);
    366             $tmp[$index]=$tmp_percentage-$result[$index];
    367             $quote_sum+=$result[$index];
    368         }
    369         if( $quote_sum == $mul) {
    370             if( $mul > 100 ) {
    371                 $tmp = $mul / 100;
    372                 for( $i=0; $i < $n; ++$i ) {
    373                     $result[$i] /= $tmp ;
    374                 }
    375             }
    376             return $result;
    377         }
    378         arsort($tmp,SORT_NUMERIC);
    379         reset($tmp);
    380         for($i=0; $i < $mul-$quote_sum; $i++)
    381         {
    382             $result[key($tmp)]++;
    383             next($tmp);
    384         }
    385         if( $mul > 100 ) {
    386             $tmp = $mul / 100;
    387             for( $i=0; $i < $n; ++$i ) {
    388                 $result[$i] /= $tmp ;
    389             }
    390         }
    391         return $result;
     344        $mul=100;
     345        if( $aPrec > 0 && $aPrec < 3 ) {
     346            if( $aPrec == 1 )
     347                $mul=1000;
     348                else
     349                    $mul=10000;
     350        }
     351       
     352        $tmp = array();
     353        $result = array();
     354        $quote_sum=0;
     355        $n = count($aData) ;
     356        for( $i=0, $sum=0; $i < $n; ++$i )
     357            $sum+=$aData[$i];
     358        foreach($aData as $index => $value) {
     359            $tmp_percentage=$value/$sum*$mul;
     360            $result[$index]=floor($tmp_percentage);
     361            $tmp[$index]=$tmp_percentage-$result[$index];
     362            $quote_sum+=$result[$index];
     363        }
     364        if( $quote_sum == $mul) {
     365            if( $mul > 100 ) {
     366                $tmp = $mul / 100;
     367                for( $i=0; $i < $n; ++$i ) {
     368                    $result[$i] /= $tmp ;
     369                }
     370            }
     371            return $result;
     372        }
     373        arsort($tmp,SORT_NUMERIC);
     374        reset($tmp);
     375        for($i=0; $i < $mul-$quote_sum; $i++)
     376        {
     377            $result[key($tmp)]++;
     378            next($tmp);
     379        }
     380        if( $mul > 100 ) {
     381            $tmp = $mul / 100;
     382            for( $i=0; $i < $n; ++$i ) {
     383                $result[$i] /= $tmp ;
     384            }
     385        }
     386        return $result;
    392387    }
    393388
    394389
    395390    function Stroke($img,$aaoption=0) {
    396         // aaoption is used to handle antialias
    397         // aaoption == 0 a normal pie
    398         // aaoption == 1 just the body
    399         // aaoption == 2 just the values
    400 
    401         // Explode scaling. If anti alias we scale the image
    402         // twice and we also need to scale the exploding distance
    403         $expscale = $aaoption === 1 ? 2 : 1;
    404 
    405         if( $this->labeltype == 2 ) {
    406             // Adjust the data so that it will add up to 100%
    407             $this->adjusted_data = $this->AdjPercentage($this->data);
    408         }
    409 
    410         if ($this->use_plot_theme_colors) {
    411             $this->setslicecolors = null;
    412         }
    413 
    414         $colors = array_keys($img->rgb->rgb_table);
    415         sort($colors);
    416         $ta=$this->themearr[$this->theme];
    417         $n = count($this->data);
    418 
    419         if( $this->setslicecolors==null ) {
    420             $numcolors=count($ta);
    421         }
    422         else {
    423             // We need to create an array of colors as long as the data
    424             // since we need to reverse it to get the colors in the right order
    425             $numcolors=count($this->setslicecolors);
    426             $i = 2*$numcolors;
    427             while( $n > $i ) {
    428                 $this->setslicecolors = array_merge($this->setslicecolors,$this->setslicecolors);
    429                 $i += $n;
    430             }
    431             $tt = array_slice($this->setslicecolors,0,$n % $numcolors);
    432             $this->setslicecolors = array_merge($this->setslicecolors,$tt);
    433             $this->setslicecolors = array_reverse($this->setslicecolors);
    434         }
    435 
    436         // Draw the slices
    437         $sum=0;
    438         for($i=0; $i < $n; ++$i)
    439             $sum += $this->data[$i];
    440 
    441         // Bail out with error if the sum is 0
    442         if( $sum==0 ) {
    443             JpGraphError::RaiseL(15009);//("Sum of all data is 0 for Pie.");
    444         }
    445 
    446         // Set up the pie-circle
    447         if( $this->radius <= 1 ) {
    448             $radius = floor($this->radius*min($img->width,$img->height));
    449         }
    450         else {
    451             $radius = $aaoption === 1 ? $this->radius*2 : $this->radius;
    452         }
    453 
    454         if( $this->posx <= 1 && $this->posx > 0 ) {
    455             $xc = round($this->posx*$img->width);
    456         }
    457         else {
    458             $xc = $this->posx ;
    459         }
    460 
    461         if( $this->posy <= 1 && $this->posy > 0 ) {
    462             $yc = round($this->posy*$img->height);
    463         }
    464         else {
    465             $yc = $this->posy ;
    466         }
    467 
    468         $n = count($this->data);
    469 
    470         if( $this->explode_all ) {
    471             for($i=0; $i < $n; ++$i) {
    472                 $this->explode_radius[$i]=$this->explode_r;
    473             }
    474         }
    475 
    476         // If we have a shadow and not just drawing the labels
    477         if( $this->ishadowcolor != "" && $aaoption !== 2) {
    478             $accsum=0;
    479             $angle2 = $this->startangle;
    480             $img->SetColor($this->ishadowcolor);
    481             for($i=0; $sum > 0 && $i < $n; ++$i) {
    482                 $j = $n-$i-1;
    483                 $d = $this->data[$i];
    484                 $angle1 = $angle2;
    485                 $accsum += $d;
    486                 $angle2 = $this->startangle+2*M_PI*$accsum/$sum;
    487                 if( empty($this->explode_radius[$j]) ) {
    488                     $this->explode_radius[$j]=0;
    489                 }
    490 
    491                 if( $d < 0.00001 ) continue;
    492 
    493                 $la = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1);
    494 
    495                 $xcm = $xc + $this->explode_radius[$j]*cos($la)*$expscale;
    496                 $ycm = $yc - $this->explode_radius[$j]*sin($la)*$expscale;
    497 
    498                 $xcm += $this->ishadowdrop*$expscale;
    499                 $ycm += $this->ishadowdrop*$expscale;
    500 
    501                 $_sa = round($angle1*180/M_PI);
    502                 $_ea = round($angle2*180/M_PI);
    503 
    504                 // The CakeSlice method draws a full circle in case of start angle = end angle
    505                 // for pie slices we don't want this behaviour unless we only have one
    506                 // slice in the pie in case it is the wanted behaviour
    507                 if( $_ea-$_sa > 0.1 || $n==1 ) {
    508                     $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1,
    509                     $angle1*180/M_PI,$angle2*180/M_PI,$this->ishadowcolor);
    510                 }
    511             }
    512         }
    513 
    514         //--------------------------------------------------------------------------------
    515         // This is the main loop to draw each cake slice
    516         //--------------------------------------------------------------------------------
    517 
    518         // Set up the accumulated sum, start angle for first slice and border color
    519         $accsum=0;
    520         $angle2 = $this->startangle;
    521         $img->SetColor($this->color);
    522 
    523         // Loop though all the slices if there is a pie to draw (sum>0)
    524         // There are n slices in total
    525         for($i=0; $sum>0 && $i < $n; ++$i) {
    526 
    527             // $j is the actual index used for the slice
    528             $j = $n-$i-1;
    529 
    530             // Make sure we havea  valid distance to explode the slice
    531             if( empty($this->explode_radius[$j]) ) {
    532                 $this->explode_radius[$j]=0;
    533             }
    534 
    535             // The actual numeric value for the slice
    536             $d = $this->data[$i];
    537 
    538             $angle1 = $angle2;
    539 
    540             // Accumlate the sum
    541             $accsum += $d;
    542 
    543             // The new angle when we add the "size" of this slice
    544             // angle1 is then the start and angle2 the end of this slice
    545             $angle2 = $this->NormAngle($this->startangle+2*M_PI*$accsum/$sum);
    546 
    547             // We avoid some trouble by not allowing end angle to be 0, in that case
    548             // we translate to 360
    549 
    550             // la is used to hold the label angle, which is centered on the slice
    551             if( $angle2 < 0.0001 && $angle1 > 0.0001 ) {
    552                 $this->la[$i] = 2*M_PI - (abs(2*M_PI-$angle1)/2.0+$angle1);
    553             }
    554             elseif( $angle1 > $angle2 ) {
    555                 // The case where the slice crosses the 3 a'clock line
    556                 // Remember that the slices are counted clockwise and
    557                 // labels are counted counter clockwise so we need to revert with 2 PI
    558                 $this->la[$i] = 2*M_PI-$this->NormAngle($angle1 + ((2*M_PI - $angle1)+$angle2)/2);
    559             }
    560             else {
    561                 $this->la[$i] = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1);
    562             }
    563 
    564             // Too avoid rounding problems we skip the slice if it is too small
    565             if( $d < 0.00001 ) continue;
    566 
    567             // If the user has specified an array of colors for each slice then use
    568             // that a color otherwise use the theme array (ta) of colors
    569             if( $this->setslicecolors==null ) {
    570                 $slicecolor=$colors[$ta[$i%$numcolors]];
    571             }
    572             else {
    573                 $slicecolor=$this->setslicecolors[$i%$numcolors];
    574             }
    575 
    576 //            $_sa = round($angle1*180/M_PI);
    577 //            $_ea = round($angle2*180/M_PI);
    578 //            $_la = round($this->la[$i]*180/M_PI);
    579 //            echo "Slice#$i: ang1=$_sa , ang2=$_ea, la=$_la, color=$slicecolor<br>";
    580 
    581 
    582             // If we have enabled antialias then we don't draw any border so
    583             // make the bordedr color the same as the slice color
    584             if( $this->pie_interior_border && $aaoption===0 ) {
    585                 $img->SetColor($this->color);
    586             }
    587             else {
    588                 $img->SetColor($slicecolor);
    589             }
    590             $arccolor = $this->pie_border && $aaoption===0 ? $this->color : "";
    591 
    592             // Calculate the x,y coordinates for the base of this slice taking
    593             // the exploded distance into account. Here we use the mid angle as the
    594             // ray of extension and we have the mid angle handy as it is also the
    595             // label angle
    596             $xcm = $xc + $this->explode_radius[$j]*cos($this->la[$i])*$expscale;
    597             $ycm = $yc - $this->explode_radius[$j]*sin($this->la[$i])*$expscale;
    598 
    599             // If we are not just drawing the labels then draw this cake slice
    600             if( $aaoption !== 2 ) {
    601 
    602                 $_sa = round($angle1*180/M_PI);
    603                 $_ea = round($angle2*180/M_PI);
    604                 $_la = round($this->la[$i]*180/M_PI);
    605                 //echo "[$i] sa=$_sa, ea=$_ea, la[$i]=$_la, (color=$slicecolor)<br>";
    606 
    607                 // The CakeSlice method draws a full circle in case of start angle = end angle
    608                 // for pie slices we want this in case the slice have a value larger than 99% of the
    609                 // total sum
    610                 if( abs($_ea-$_sa) >= 1 || $d == $sum ) {
    611                     $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1,$_sa,$_ea,$slicecolor,$arccolor);
    612                 }
    613             }
    614 
    615             // If the CSIM is used then make sure we register a CSIM area for this slice as well
    616             if( $this->csimtargets && $aaoption !== 1 ) {
    617                 $this->AddSliceToCSIM($i,$xcm,$ycm,$radius,$angle1,$angle2);
    618             }
    619         }
    620 
    621         // Format the titles for each slice
    622         if( $aaoption !== 2 ) {
    623             for( $i=0; $i < $n; ++$i) {
    624                 if( $this->labeltype==0 ) {
    625                     if( $sum != 0 )
    626                     $l = 100.0*$this->data[$i]/$sum;
    627                     else
    628                     $l = 0.0;
    629                 }
    630                 elseif( $this->labeltype==1 ) {
    631                     $l = $this->data[$i]*1.0;
    632                 }
    633                 else {
    634                     $l = $this->adjusted_data[$i];
    635                 }
    636                 if( isset($this->labels[$i]) && is_string($this->labels[$i]) )
    637                 $this->labels[$i]=sprintf($this->labels[$i],$l);
    638                 else
    639                 $this->labels[$i]=$l;
    640             }
    641         }
    642 
    643         if( $this->value->show && $aaoption !== 1 ) {
    644             $this->StrokeAllLabels($img,$xc,$yc,$radius);
    645         }
    646 
    647         // Adjust title position
    648         if( $aaoption !== 1 ) {
    649             $this->title->SetPos($xc,
    650             $yc-$this->title->GetFontHeight($img)-$radius-$this->title->margin,
    651      "center","bottom");
    652             $this->title->Stroke($img);
    653         }
    654 
    655     }
    656 
    657     //---------------
    658     // PRIVATE METHODS
     391        // aaoption is used to handle antialias
     392        // aaoption == 0 a normal pie
     393        // aaoption == 1 just the body
     394        // aaoption == 2 just the values
     395
     396        // Explode scaling. If anti anti alias we scale the image
     397        // twice and we also need to scale the exploding distance
     398        $expscale = $aaoption === 1 ? 2 : 1;
     399
     400        if( $this->labeltype == 2 ) {
     401            // Adjust the data so that it will add up to 100%
     402            $this->adjusted_data = $this->AdjPercentage($this->data);
     403        }
     404
     405        $colors = array_keys($img->rgb->rgb_table);
     406        sort($colors); 
     407        $ta=$this->themearr[$this->theme];     
     408        $n = count($this->data);
     409       
     410        if( $this->setslicecolors==null ) {
     411            $numcolors=count($ta);
     412        }
     413        else {
     414            // We need to create an array of colors as long as the data
     415            // since we need to reverse it to get the colors in the right order
     416            $numcolors=count($this->setslicecolors);
     417            $i = 2*$numcolors;
     418            while( $n > $i ) {
     419                $this->setslicecolors = array_merge($this->setslicecolors,$this->setslicecolors);
     420                $i += $n;
     421            }
     422            $tt = array_slice($this->setslicecolors,0,$n % $numcolors);
     423            $this->setslicecolors = array_merge($this->setslicecolors,$tt);
     424            $this->setslicecolors = array_reverse($this->setslicecolors);
     425        }
     426
     427        // Draw the slices
     428        $sum=0;
     429        for($i=0; $i < $n; ++$i)
     430            $sum += $this->data[$i];
     431       
     432        // Bail out with error if the sum is 0
     433        if( $sum==0 )
     434            JpGraphError::RaiseL(15009);//("Sum of all data is 0 for Pie.");
     435       
     436        // Set up the pie-circle
     437        if( $this->radius <= 1 )
     438            $radius = floor($this->radius*min($img->width,$img->height));
     439        else {
     440            $radius = $aaoption === 1 ? $this->radius*2 : $this->radius;
     441        }
     442
     443        if( $this->posx <= 1 && $this->posx > 0 )
     444            $xc = round($this->posx*$img->width);
     445        else
     446            $xc = $this->posx ;
     447       
     448        if( $this->posy <= 1 && $this->posy > 0 )
     449            $yc = round($this->posy*$img->height);
     450        else
     451            $yc = $this->posy ;
     452               
     453        $n = count($this->data);
     454
     455        if( $this->explode_all )
     456            for($i=0; $i < $n; ++$i)
     457                $this->explode_radius[$i]=$this->explode_r;
     458
     459        // If we have a shadow and not just drawing the labels
     460        if( $this->ishadowcolor != "" && $aaoption !== 2) {
     461            $accsum=0;
     462            $angle2 = $this->startangle;
     463            $img->SetColor($this->ishadowcolor);
     464            for($i=0; $sum > 0 && $i < $n; ++$i) {
     465                $j = $n-$i-1;
     466                $d = $this->data[$i];
     467                $angle1 = $angle2;
     468                $accsum += $d;
     469                $angle2 = $this->startangle+2*M_PI*$accsum/$sum;
     470                if( empty($this->explode_radius[$j]) )
     471                    $this->explode_radius[$j]=0;
     472
     473                if( $d < 0.00001 ) continue;
     474
     475                $la = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1);
     476
     477                $xcm = $xc + $this->explode_radius[$j]*cos($la)*$expscale;
     478                $ycm = $yc - $this->explode_radius[$j]*sin($la)*$expscale;
     479               
     480                $xcm += $this->ishadowdrop*$expscale;
     481                $ycm += $this->ishadowdrop*$expscale;
     482
     483                $_sa = round($angle1*180/M_PI);
     484                $_ea = round($angle2*180/M_PI);
     485
     486                // The CakeSlice method draws a full circle in case of start angle = end angle
     487                // for pie slices we don't want this behaviour unless we only have one
     488                // slice in the pie in case it is the wanted behaviour
     489                if( $_ea-$_sa > 0.1 || $n==1 ) {
     490                    $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1,
     491                                    $angle1*180/M_PI,$angle2*180/M_PI,$this->ishadowcolor);
     492                }
     493            }
     494        }
     495
     496        //--------------------------------------------------------------------------------
     497        // This is the main loop to draw each cake slice
     498        //--------------------------------------------------------------------------------
     499
     500        // Set up the accumulated sum, start angle for first slice and border color
     501        $accsum=0;
     502        $angle2 = $this->startangle;
     503        $img->SetColor($this->color);
     504
     505        // Loop though all the slices if there is a pie to draw (sum>0)
     506        // There are n slices in total
     507        for($i=0; $sum>0 && $i < $n; ++$i) {
     508
     509            // $j is the actual index used for the slice
     510            $j = $n-$i-1;
     511
     512            // Make sure we havea  valid distance to explode the slice
     513            if( empty($this->explode_radius[$j]) )
     514                $this->explode_radius[$j]=0;
     515
     516            // The actual numeric value for the slice
     517            $d = $this->data[$i];
     518
     519            $angle1 = $angle2;
     520
     521            // Accumlate the sum
     522            $accsum += $d;
     523
     524            // The new angle when we add the "size" of this slice
     525            // angle1 is then the start and angle2 the end of this slice
     526            $angle2 = $this->NormAngle($this->startangle+2*M_PI*$accsum/$sum);
     527
     528            // We avoid some trouble by not allowing end angle to be 0, in that case
     529            // we translate to 360
     530
     531
     532            // la is used to hold the label angle, which is centered on the slice
     533            if( $angle2 < 0.0001 && $angle1 > 0.0001 ) {
     534                $this->la[$i] = 2*M_PI - (abs(2*M_PI-$angle1)/2.0+$angle1);
     535            }
     536            elseif( $angle1 > $angle2 ) {
     537                // The case where the slice crosses the 3 a'clock line
     538                // Remember that the slices are counted clockwise and
     539                // labels are counted counter clockwise so we need to revert with 2 PI
     540                $this->la[$i] = 2*M_PI-$this->NormAngle($angle1 + ((2*M_PI - $angle1)+$angle2)/2);
     541            }
     542            else {
     543                $this->la[$i] = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1);
     544            }
     545
     546            // Too avoid rounding problems we skip the slice if it is too small
     547            if( $d < 0.00001 ) continue;
     548
     549            // If the user has specified an array of colors for each slice then use
     550            // that a color otherwise use the theme array (ta) of colors
     551            if( $this->setslicecolors==null )
     552                $slicecolor=$colors[$ta[$i%$numcolors]];
     553            else
     554                $slicecolor=$this->setslicecolors[$i%$numcolors];
     555           
     556
     557           
     558//$_sa = round($angle1*180/M_PI);
     559//$_ea = round($angle2*180/M_PI);
     560//$_la = round($this->la[$i]*180/M_PI);
     561//echo "ang1=$_sa , ang2=$_ea, la=$_la, color=$slicecolor<br>";
     562
     563
     564            // If we have enabled antialias then we don't draw any border so
     565            // make the bordedr color the same as the slice color
     566            if( $this->pie_interior_border && $aaoption===0 )
     567                $img->SetColor($this->color);
     568            else
     569                $img->SetColor($slicecolor);       
     570            $arccolor = $this->pie_border && $aaoption===0 ? $this->color : "";
     571
     572            // Calculate the x,y coordinates for the base of this slice taking
     573            // the exploded distance into account. Here we use the mid angle as the
     574            // ray of extension and we have the mid angle handy as it is also the
     575            // label angle
     576            $xcm = $xc + $this->explode_radius[$j]*cos($this->la[$i])*$expscale;
     577            $ycm = $yc - $this->explode_radius[$j]*sin($this->la[$i])*$expscale;
     578
     579            // If we are not just drawing the labels then draw this cake slice
     580            if( $aaoption !== 2 ) {
     581
     582               
     583                $_sa = round($angle1*180/M_PI);
     584                $_ea = round($angle2*180/M_PI);
     585                $_la = round($this->la[$i]*180/M_PI);
     586                //echo "[$i] sa=$_sa, ea=$_ea, la[$i]=$_la, (color=$slicecolor)<br>";
     587               
     588
     589                // The CakeSlice method draws a full circle in case of start angle = end angle
     590                // for pie slices we don't want this behaviour unless we only have one
     591                // slice in the pie in case it is the wanted behaviour
     592                if( abs($_ea-$_sa) > 0.1 || $n==1 ) {
     593                    $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1,$_sa,$_ea,$slicecolor,$arccolor);
     594                }
     595            }
     596
     597            // If the CSIM is used then make sure we register a CSIM area for this slice as well
     598            if( $this->csimtargets && $aaoption !== 1 ) {
     599                $this->AddSliceToCSIM($i,$xcm,$ycm,$radius,$angle1,$angle2);
     600            }
     601        }
     602
     603        // Format the titles for each slice
     604        if( $aaoption !== 2 ) {
     605            for( $i=0; $i < $n; ++$i) {
     606                if( $this->labeltype==0 ) {
     607                    if( $sum != 0 )
     608                        $l = 100.0*$this->data[$i]/$sum;
     609                    else
     610                        $l = 0.0;
     611                }
     612                elseif( $this->labeltype==1 ) {
     613                    $l = $this->data[$i]*1.0;
     614                }
     615                else {
     616                    $l = $this->adjusted_data[$i];
     617                }
     618                if( isset($this->labels[$i]) && is_string($this->labels[$i]) )
     619                    $this->labels[$i]=sprintf($this->labels[$i],$l);
     620                else
     621                    $this->labels[$i]=$l;
     622            }
     623        }
     624
     625        if( $this->value->show && $aaoption !== 1 ) {
     626            $this->StrokeAllLabels($img,$xc,$yc,$radius);
     627        }
     628
     629        // Adjust title position
     630        if( $aaoption !== 1 ) {
     631            $this->title->SetPos($xc,
     632                          $yc-$this->title->GetFontHeight($img)-$radius-$this->title->margin,
     633                          "center","bottom");
     634            $this->title->Stroke($img);
     635        }
     636
     637    }
     638
     639//---------------
     640// PRIVATE METHODS     
    659641
    660642    function NormAngle($a) {
    661         while( $a < 0 ) $a += 2*M_PI;
    662         while( $a > 2*M_PI ) $a -= 2*M_PI;
    663         return $a;
     643        while( $a < 0 ) $a += 2*M_PI;
     644        while( $a > 2*M_PI ) $a -= 2*M_PI;
     645        return $a;
    664646    }
    665647
    666648    function Quadrant($a) {
    667         $a=$this->NormAngle($a);
    668         if( $a > 0 && $a <= M_PI/2 )
    669         return 0;
    670         if( $a > M_PI/2 && $a <= M_PI )
    671         return 1;
    672         if( $a > M_PI && $a <= 1.5*M_PI )
    673         return 2;
    674         if( $a > 1.5*M_PI )
    675         return 3;
     649        $a=$this->NormAngle($a);
     650        if( $a > 0 && $a <= M_PI/2 )
     651            return 0;
     652        if( $a > M_PI/2 && $a <= M_PI )
     653            return 1;
     654        if( $a > M_PI && $a <= 1.5*M_PI )
     655            return 2;
     656        if( $a > 1.5*M_PI )
     657            return 3;
    676658    }
    677659
    678660    function StrokeGuideLabels($img,$xc,$yc,$radius) {
    679         $n = count($this->labels);
    680 
    681         //-----------------------------------------------------------------------
    682         // Step 1 of the algorithm is to construct a number of clusters
    683         // a cluster is defined as all slices within the same quadrant (almost)
    684         // that has an angular distance less than the treshold
    685         //-----------------------------------------------------------------------
    686         $tresh_hold=25 * M_PI/180; // 25 degrees difference to be in a cluster
    687         $incluster=false; // flag if we are currently in a cluster or not
    688         $clusters = array(); // array of clusters
    689         $cidx=-1;  // running cluster index
    690 
    691         // Go through all the labels and construct a number of clusters
    692         for($i=0; $i < $n-1; ++$i) {
    693             // Calc the angle distance between two consecutive slices
    694             $a1=$this->la[$i];
    695             $a2=$this->la[$i+1];
    696             $q1 = $this->Quadrant($a1);
    697             $q2 = $this->Quadrant($a2);
    698             $diff = abs($a1-$a2);
    699             if( $diff < $tresh_hold ) {
    700                 if( $incluster ) {
    701                     $clusters[$cidx][1]++;
    702                     // Each cluster can only cover one quadrant
    703                     // Do we cross a quadrant ( and must break the cluster)
    704                     if( $q1 !=  $q2 ) {
    705                         // If we cross a quadrant boundary we normally start a
    706                         // new cluster. However we need to take the 12'a clock
    707                         // and 6'a clock positions into a special consideration.
    708                         // Case 1: WE go from q=1 to q=2 if the last slice on
    709                         // the cluster for q=1 is close to 12'a clock and the
    710                         // first slice in q=0 is small we extend the previous
    711                         // cluster
    712                         if( $q1 == 1 && $q2 == 0 && $a2 > (90-15)*M_PI/180 ) {
    713                             if( $i < $n-2 ) {
    714                                 $a3 = $this->la[$i+2];
    715                                 // If there isn't a cluster coming up with the next-next slice
    716                                 // we extend the previous cluster to cover this slice as well
    717                                 if( abs($a3-$a2) >= $tresh_hold ) {
    718                                     $clusters[$cidx][1]++;
    719                                     $i++;
    720                                 }
    721                             }
    722                         }
    723                         elseif( $q1 == 3 && $q2 == 2 && $a2 > (270-15)*M_PI/180 ) {
    724                             if( $i < $n-2 ) {
    725                                 $a3 = $this->la[$i+2];
    726                                 // If there isn't a cluster coming up with the next-next slice
    727                                 // we extend the previous cluster to cover this slice as well
    728                                 if( abs($a3-$a2) >= $tresh_hold ) {
    729                                     $clusters[$cidx][1]++;
    730                                     $i++;
    731                                 }
    732                             }
    733                         }
    734 
    735                         if( $q1==2 && $q2==1 && $a2 > (180-15)*M_PI/180 ) {
    736                             $clusters[$cidx][1]++;
    737                             $i++;
    738                         }
    739 
    740                         $incluster = false;
    741                     }
    742                 }
    743                 elseif( $q1 == $q2)  {
    744                     $incluster = true;
    745                     // Now we have a special case for quadrant 0. If we previously
    746                     // have a cluster of one in quadrant 0 we just extend that
    747                     // cluster. If we don't do this then we risk that the label
    748                     // for the cluster of one will cross the guide-line
    749                     if( $q1 == 0 && $cidx > -1 &&
    750                     $clusters[$cidx][1] == 1 &&
    751                     $this->Quadrant($this->la[$clusters[$cidx][0]]) == 0 ) {
    752                         $clusters[$cidx][1]++;
    753                     }
    754                     else {
    755                         $cidx++;
    756                         $clusters[$cidx][0] = $i;
    757                         $clusters[$cidx][1] = 1;
    758                     }
    759                 }
    760                 else {
    761                     // Create a "cluster" of one since we are just crossing
    762                     // a quadrant
    763                     $cidx++;
    764                     $clusters[$cidx][0] = $i;
    765                     $clusters[$cidx][1] = 1;
    766                 }
    767             }
    768             else {
    769                 if( $incluster ) {
    770                     // Add the last slice
    771                     $clusters[$cidx][1]++;
    772                     $incluster = false;
    773                 }
    774                 else { // Create a "cluster" of one
    775                     $cidx++;
    776                     $clusters[$cidx][0] = $i;
    777                     $clusters[$cidx][1] = 1;
    778                 }
    779             }
    780         }
    781         // Handle the very last slice
    782         if( $incluster ) {
    783             $clusters[$cidx][1]++;
    784         }
    785         else { // Create a "cluster" of one
    786             $cidx++;
    787             $clusters[$cidx][0] = $i;
    788             $clusters[$cidx][1] = 1;
    789         }
    790 
    791         /*
    792          if( true ) {
    793          // Debug printout in labels
    794          for( $i=0; $i <= $cidx; ++$i ) {
    795          for( $j=0; $j < $clusters[$i][1]; ++$j ) {
    796          $a = $this->la[$clusters[$i][0]+$j];
    797          $aa = round($a*180/M_PI);
    798          $q = $this->Quadrant($a);
    799          $this->labels[$clusters[$i][0]+$j]="[$q:$aa] $i:$j";
    800          }
    801          }
    802          }
    803          */
    804 
    805         //-----------------------------------------------------------------------
    806         // Step 2 of the algorithm is use the clusters and draw the labels
    807         // and guidelines
    808         //-----------------------------------------------------------------------
    809 
    810         // We use the font height as the base factor for how far we need to
    811         // spread the labels in the Y-direction.
    812         $this->value->ApplyFont($img);
    813         $fh = $img->GetFontHeight();
    814         $origvstep=$fh*$this->iGuideVFactor;
    815         $this->value->SetMargin(0);
    816 
    817         // Number of clusters found
    818         $nc = count($clusters);
    819 
    820         // Walk through all the clusters
    821         for($i=0; $i < $nc; ++$i) {
    822 
    823             // Start angle and number of slices in this cluster
    824             $csize = $clusters[$i][1];
    825             $a = $this->la[$clusters[$i][0]];
    826             $q = $this->Quadrant($a);
    827 
    828             // Now set up the start and end conditions to make sure that
    829             // in each cluster we walk through the all the slices starting with the slice
    830             // closest to the equator. Since all slices are numbered clockwise from "3'a clock"
    831             // we have different conditions depending on in which quadrant the slice lies within.
    832             if( $q == 0 ) {
    833                 $start = $csize-1; $idx = $start; $step = -1; $vstep = -$origvstep;
    834             }
    835             elseif( $q == 1 ) {
    836                 $start = 0; $idx = $start; $step = 1; $vstep = -$origvstep;
    837             }
    838             elseif( $q == 2 ) {
    839                 $start = $csize-1; $idx = $start; $step = -1; $vstep = $origvstep;
    840             }
    841             elseif( $q == 3 ) {
    842                 $start = 0; $idx = $start; $step = 1; $vstep = $origvstep;
    843             }
    844 
    845             // Walk through all slices within this cluster
    846             for($j=0; $j < $csize; ++$j) {
    847                 // Now adjust the position of the labels in each cluster starting
    848                 // with the slice that is closest to the equator of the pie
    849                 $a = $this->la[$clusters[$i][0]+$idx];
    850 
    851                 // Guide line start in the center of the arc of the slice
    852                 $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)];
    853                 $x = round($r*cos($a)+$xc);
    854                 $y = round($yc-$r*sin($a));
    855 
    856                 // The distance from the arc depends on chosen font and the "R-Factor"
    857                 $r += $fh*$this->iGuideLineRFactor;
    858 
    859                 // Should the labels be placed curved along the pie or in straight columns
    860                 // outside the pie?
    861                 if( $this->iGuideLineCurve )
    862                 $xt=round($r*cos($a)+$xc);
    863 
    864                 // If this is the first slice in the cluster we need some first time
    865                 // proessing
    866                 if( $idx == $start ) {
    867                     if( ! $this->iGuideLineCurve )
    868                     $xt=round($r*cos($a)+$xc);
    869                     $yt=round($yc-$r*sin($a));
    870 
    871                     // Some special consideration in case this cluster starts
    872                     // in quadrant 1 or 3 very close to the "equator" (< 20 degrees)
    873                     // and the previous clusters last slice is within the tolerance.
    874                     // In that case we add a font height to this labels Y-position
    875                     // so it doesn't collide with
    876                     // the slice in the previous cluster
    877                     $prevcluster = ($i + ($nc-1) ) % $nc;
    878                     $previdx=$clusters[$prevcluster][0]+$clusters[$prevcluster][1]-1;
    879                     if( $q == 1 && $a > 160*M_PI/180 ) {
    880                         // Get the angle for the previous clusters last slice
    881                         $diff = abs($a-$this->la[$previdx]);
    882                         if( $diff < $tresh_hold ) {
    883                             $yt -= $fh;
    884                         }
    885                     }
    886                     elseif( $q == 3 && $a > 340*M_PI/180 ) {
    887                         // We need to subtract 360 to compare angle distance between
    888                         // q=0 and q=3
    889                         $diff = abs($a-$this->la[$previdx]-360*M_PI/180);
    890                         if( $diff < $tresh_hold ) {
    891                             $yt += $fh;
    892                         }
    893                     }
    894 
    895                 }
    896                 else {
    897                     // The step is at minimum $vstep but if the slices are relatively large
    898                     // we make sure that we add at least a step that corresponds to the vertical
    899                     // distance between the centers at the arc on the slice
    900                     $prev_a = $this->la[$clusters[$i][0]+($idx-$step)];
    901                     $dy = abs($radius*(sin($a)-sin($prev_a))*1.2);
    902                     if( $vstep > 0 )
    903                     $yt += max($vstep,$dy);
    904                     else
    905                     $yt += min($vstep,-$dy);
    906                 }
    907 
    908                 $label = $this->labels[$clusters[$i][0]+$idx];
    909 
    910                 if( $csize == 1 ) {
    911                     // A "meta" cluster with only one slice
    912                     $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)];
    913                     $rr = $r+$img->GetFontHeight()/2;
    914                     $xt=round($rr*cos($a)+$xc);
    915                     $yt=round($yc-$rr*sin($a));
    916                     $this->StrokeLabel($label,$img,$xc,$yc,$a,$r);
    917                     if( $this->iShowGuideLineForSingle )
    918                     $this->guideline->Stroke($img,$x,$y,$xt,$yt);
    919                 }
    920                 else {
    921                     $this->guideline->Stroke($img,$x,$y,$xt,$yt);
    922                     if( $q==1 || $q==2 ) {
    923                         // Left side of Pie
    924                         $this->guideline->Stroke($img,$xt,$yt,$xt-$this->guidelinemargin,$yt);
    925                         $lbladj = -$this->guidelinemargin-5;
    926                         $this->value->halign = "right";
    927                         $this->value->valign = "center";
    928                     }
    929                     else {
    930                         // Right side of pie
    931                         $this->guideline->Stroke($img,$xt,$yt,$xt+$this->guidelinemargin,$yt);
    932                         $lbladj = $this->guidelinemargin+5;
    933                         $this->value->halign = "left";
    934                         $this->value->valign = "center";
    935                     }
    936                     $this->value->Stroke($img,$label,$xt+$lbladj,$yt);
    937                 }
    938 
    939                 // Udate idx to point to next slice in the cluster to process
    940                 $idx += $step;
    941             }
    942         }
     661        $n = count($this->labels);
     662
     663        //-----------------------------------------------------------------------
     664        // Step 1 of the algorithm is to construct a number of clusters
     665        // a cluster is defined as all slices within the same quadrant (almost)
     666        // that has an angular distance less than the treshold
     667        //-----------------------------------------------------------------------
     668        $tresh_hold=25 * M_PI/180; // 25 degrees difference to be in a cluster
     669        $incluster=false;       // flag if we are currently in a cluster or not
     670        $clusters = array();    // array of clusters
     671        $cidx=-1;               // running cluster index
     672
     673        // Go through all the labels and construct a number of clusters
     674        for($i=0; $i < $n-1; ++$i) {
     675            // Calc the angle distance between two consecutive slices
     676            $a1=$this->la[$i];
     677            $a2=$this->la[$i+1];
     678            $q1 = $this->Quadrant($a1);
     679            $q2 = $this->Quadrant($a2);
     680            $diff = abs($a1-$a2);
     681            if( $diff < $tresh_hold ) {
     682                if( $incluster ) {
     683                    $clusters[$cidx][1]++;
     684                    // Each cluster can only cover one quadrant
     685                    // Do we cross a quadrant ( and must break the cluster)
     686                    if( $q1 !=  $q2 ) {
     687                        // If we cross a quadrant boundary we normally start a
     688                        // new cluster. However we need to take the 12'a clock
     689                        // and 6'a clock positions into a special consideration.
     690                        // Case 1: WE go from q=1 to q=2 if the last slice on
     691                        // the cluster for q=1 is close to 12'a clock and the
     692                        // first slice in q=0 is small we extend the previous
     693                        // cluster
     694                        if( $q1 == 1 && $q2 == 0 && $a2 > (90-15)*M_PI/180 ) {
     695                            if( $i < $n-2 ) {
     696                                $a3 = $this->la[$i+2];
     697                                // If there isn't a cluster coming up with the next-next slice
     698                                // we extend the previous cluster to cover this slice as well
     699                                if( abs($a3-$a2) >= $tresh_hold ) {
     700                                    $clusters[$cidx][1]++;
     701                                    $i++;
     702                                }
     703                            }
     704                        }
     705                        elseif( $q1 == 3 && $q2 == 2 && $a2 > (270-15)*M_PI/180 ) {
     706                            if( $i < $n-2 ) {
     707                                $a3 = $this->la[$i+2];
     708                                // If there isn't a cluster coming up with the next-next slice
     709                                // we extend the previous cluster to cover this slice as well
     710                                if( abs($a3-$a2) >= $tresh_hold ) {
     711                                    $clusters[$cidx][1]++;
     712                                    $i++;
     713                                }
     714                            }
     715                        }
     716
     717                        if( $q1==2 && $q2==1 && $a2 > (180-15)*M_PI/180 ) {
     718                            $clusters[$cidx][1]++;
     719                            $i++;                           
     720                        }
     721                       
     722                        $incluster = false;
     723                    }
     724                }
     725                elseif( $q1 == $q2)  {
     726                    $incluster = true;
     727                    // Now we have a special case for quadrant 0. If we previously
     728                    // have a cluster of one in quadrant 0 we just extend that
     729                    // cluster. If we don't do this then we risk that the label
     730                    // for the cluster of one will cross the guide-line
     731                    if( $q1 == 0 && $cidx > -1 &&
     732                        $clusters[$cidx][1] == 1 &&
     733                        $this->Quadrant($this->la[$clusters[$cidx][0]]) == 0 ) {
     734                        $clusters[$cidx][1]++;
     735                    }
     736                    else {
     737                        $cidx++;
     738                        $clusters[$cidx][0] = $i;
     739                        $clusters[$cidx][1] = 1;
     740                    }
     741                }
     742                else { 
     743                    // Create a "cluster" of one since we are just crossing
     744                    // a quadrant
     745                    $cidx++;
     746                    $clusters[$cidx][0] = $i;
     747                    $clusters[$cidx][1] = 1;       
     748                }
     749            }
     750            else {
     751                if( $incluster ) {
     752                    // Add the last slice
     753                    $clusters[$cidx][1]++;
     754                    $incluster = false;
     755                }
     756                else { // Create a "cluster" of one
     757                    $cidx++;
     758                    $clusters[$cidx][0] = $i;
     759                    $clusters[$cidx][1] = 1;       
     760                }
     761            }
     762        }
     763        // Handle the very last slice
     764        if( $incluster ) {
     765            $clusters[$cidx][1]++;
     766        }
     767        else { // Create a "cluster" of one
     768            $cidx++;
     769            $clusters[$cidx][0] = $i;
     770            $clusters[$cidx][1] = 1;       
     771        }
     772
     773        /*
     774        if( true ) {
     775            // Debug printout in labels
     776            for( $i=0; $i <= $cidx; ++$i ) {
     777                for( $j=0; $j < $clusters[$i][1]; ++$j ) {
     778                    $a = $this->la[$clusters[$i][0]+$j];
     779                    $aa = round($a*180/M_PI);
     780                    $q = $this->Quadrant($a);
     781                    $this->labels[$clusters[$i][0]+$j]="[$q:$aa] $i:$j";
     782                }
     783            }
     784        }
     785        */
     786
     787        //-----------------------------------------------------------------------
     788        // Step 2 of the algorithm is use the clusters and draw the labels
     789        // and guidelines
     790        //-----------------------------------------------------------------------
     791
     792        // We use the font height as the base factor for how far we need to
     793        // spread the labels in the Y-direction.
     794        $this->value->ApplyFont($img);
     795        $fh = $img->GetFontHeight();
     796        $origvstep=$fh*$this->iGuideVFactor;
     797        $this->value->SetMargin(0);
     798
     799        // Number of clusters found
     800        $nc = count($clusters);
     801
     802        // Walk through all the clusters
     803        for($i=0; $i < $nc; ++$i) {
     804
     805            // Start angle and number of slices in this cluster
     806            $csize = $clusters[$i][1];
     807            $a = $this->la[$clusters[$i][0]];
     808            $q = $this->Quadrant($a);
     809
     810            // Now set up the start and end conditions to make sure that
     811            // in each cluster we walk through the all the slices starting with the slice
     812            // closest to the equator. Since all slices are numbered clockwise from "3'a clock"
     813            // we have different conditions depending on in which quadrant the slice lies within.
     814            if( $q == 0 ) {
     815                $start = $csize-1; $idx = $start; $step = -1; $vstep = -$origvstep;
     816            }
     817            elseif( $q == 1 ) {
     818                $start = 0; $idx = $start; $step = 1; $vstep = -$origvstep;
     819            }
     820            elseif( $q == 2 ) {
     821                $start = $csize-1; $idx = $start; $step = -1; $vstep = $origvstep;
     822            }
     823            elseif( $q == 3 ) {
     824                $start = 0; $idx = $start; $step = 1; $vstep = $origvstep;
     825            }
     826
     827            // Walk through all slices within this cluster
     828            for($j=0; $j < $csize; ++$j) {   
     829                // Now adjust the position of the labels in each cluster starting
     830                // with the slice that is closest to the equator of the pie
     831                $a = $this->la[$clusters[$i][0]+$idx];
     832                   
     833                // Guide line start in the center of the arc of the slice
     834                $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)];
     835                $x = round($r*cos($a)+$xc);
     836                $y = round($yc-$r*sin($a));
     837               
     838                // The distance from the arc depends on chosen font and the "R-Factor"
     839                $r += $fh*$this->iGuideLineRFactor;
     840
     841                // Should the labels be placed curved along the pie or in straight columns
     842                // outside the pie?
     843                if( $this->iGuideLineCurve )
     844                    $xt=round($r*cos($a)+$xc);
     845
     846                // If this is the first slice in the cluster we need some first time
     847                // proessing
     848                if( $idx == $start ) {
     849                    if( ! $this->iGuideLineCurve )
     850                        $xt=round($r*cos($a)+$xc);
     851                    $yt=round($yc-$r*sin($a));
     852
     853                    // Some special consideration in case this cluster starts
     854                    // in quadrant 1 or 3 very close to the "equator" (< 20 degrees)
     855                    // and the previous clusters last slice is within the tolerance.
     856                    // In that case we add a font height to this labels Y-position
     857                    // so it doesn't collide with
     858                    // the slice in the previous cluster
     859                    $prevcluster = ($i + ($nc-1) ) % $nc;
     860                    $previdx=$clusters[$prevcluster][0]+$clusters[$prevcluster][1]-1;
     861                    if( $q == 1 && $a > 160*M_PI/180 ) {
     862                        // Get the angle for the previous clusters last slice
     863                        $diff = abs($a-$this->la[$previdx]);
     864                        if( $diff < $tresh_hold ) {
     865                             $yt -= $fh;
     866                        }
     867                    }
     868                    elseif( $q == 3 && $a > 340*M_PI/180 ) {
     869                        // We need to subtract 360 to compare angle distance between
     870                        // q=0 and q=3
     871                        $diff = abs($a-$this->la[$previdx]-360*M_PI/180);
     872                        if( $diff < $tresh_hold ) {
     873                             $yt += $fh;
     874                        }
     875                    }
     876
     877                }
     878                else {
     879                    // The step is at minimum $vstep but if the slices are relatively large
     880                    // we make sure that we add at least a step that corresponds to the vertical
     881                    // distance between the centers at the arc on the slice
     882                    $prev_a = $this->la[$clusters[$i][0]+($idx-$step)];
     883                    $dy = abs($radius*(sin($a)-sin($prev_a))*1.2);
     884                    if( $vstep > 0 )
     885                        $yt += max($vstep,$dy);
     886                    else
     887                        $yt += min($vstep,-$dy);
     888                }
     889
     890                $label = $this->labels[$clusters[$i][0]+$idx];
     891
     892                if( $csize == 1 ) {
     893                    // A "meta" cluster with only one slice
     894                    $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)];
     895                    $rr = $r+$img->GetFontHeight()/2;
     896                    $xt=round($rr*cos($a)+$xc);
     897                    $yt=round($yc-$rr*sin($a));
     898                    $this->StrokeLabel($label,$img,$xc,$yc,$a,$r);
     899                    if( $this->iShowGuideLineForSingle )
     900                        $this->guideline->Stroke($img,$x,$y,$xt,$yt);
     901                }
     902                else {
     903                    $this->guideline->Stroke($img,$x,$y,$xt,$yt);
     904                    if( $q==1 || $q==2 ) {
     905                        // Left side of Pie
     906                        $this->guideline->Stroke($img,$xt,$yt,$xt-$this->guidelinemargin,$yt);
     907                        $lbladj = -$this->guidelinemargin-5;
     908                        $this->value->halign = "right";
     909                        $this->value->valign = "center";
     910                    }
     911                    else {
     912                        // Right side of pie
     913                        $this->guideline->Stroke($img,$xt,$yt,$xt+$this->guidelinemargin,$yt);
     914                        $lbladj = $this->guidelinemargin+5;
     915                        $this->value->halign = "left";
     916                        $this->value->valign = "center";
     917                    }
     918                    $this->value->Stroke($img,$label,$xt+$lbladj,$yt);
     919                }
     920
     921                // Udate idx to point to next slice in the cluster to process
     922                $idx += $step;
     923            }
     924        }
    943925    }
    944926
    945927    function StrokeAllLabels($img,$xc,$yc,$radius) {
    946         // First normalize all angles for labels
    947         $n = count($this->la);
    948         for($i=0; $i < $n; ++$i) {
    949             $this->la[$i] = $this->NormAngle($this->la[$i]);
    950         }
    951         if( $this->guideline->iShow ) {
    952             $this->StrokeGuideLabels($img,$xc,$yc,$radius);
    953         }
    954         else {
    955             $n = count($this->labels);
    956             for($i=0; $i < $n; ++$i) {
    957                 $this->StrokeLabel($this->labels[$i],$img,$xc,$yc,
    958                 $this->la[$i],
    959                 $radius + $this->explode_radius[$n-1-$i]);
    960             }
    961         }
     928        // First normalize all angles for labels
     929        $n = count($this->la);
     930        for($i=0; $i < $n; ++$i) {
     931            $this->la[$i] = $this->NormAngle($this->la[$i]);
     932        }
     933        if( $this->guideline->iShow ) {
     934            $this->StrokeGuideLabels($img,$xc,$yc,$radius);
     935        }
     936        else {
     937            $n = count($this->labels);
     938            for($i=0; $i < $n; ++$i) {
     939                $this->StrokeLabel($this->labels[$i],$img,$xc,$yc,
     940                                   $this->la[$i],
     941                                   $radius + $this->explode_radius[$n-1-$i]);
     942            }
     943        }
    962944    }
    963945
     
    965947    function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
    966948
    967         // Default value
    968         if( $this->ilabelposadj === 'auto' )
    969         $this->ilabelposadj = 0.65;
    970 
    971         // We position the values diferently depending on if they are inside
    972         // or outside the pie
    973         if( $this->ilabelposadj < 1.0 ) {
    974 
    975             $this->value->SetAlign('center','center');
    976             $this->value->margin = 0;
    977 
    978             $xt=round($this->ilabelposadj*$r*cos($a)+$xc);
    979             $yt=round($yc-$this->ilabelposadj*$r*sin($a));
    980 
    981             $this->value->Stroke($img,$label,$xt,$yt);
    982         }
    983         else {
    984 
    985             $this->value->halign = "left";
    986             $this->value->valign = "top";
    987             $this->value->margin = 0;
    988 
    989             // Position the axis title.
    990             // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
    991             // that intersects with the extension of the corresponding axis. The code looks a little
    992             // bit messy but this is really the only way of having a reasonable position of the
    993             // axis titles.
    994             $this->value->ApplyFont($img);
    995             $h=$img->GetTextHeight($label);
    996             // For numeric values the format of the display value
    997             // must be taken into account
    998             if( is_numeric($label) ) {
    999                 if( $label > 0 )
    1000                 $w=$img->GetTextWidth(sprintf($this->value->format,$label));
    1001                 else
    1002                 $w=$img->GetTextWidth(sprintf($this->value->negformat,$label));
    1003             }
    1004             else
    1005             $w=$img->GetTextWidth($label);
    1006 
    1007             if( $this->ilabelposadj > 1.0 && $this->ilabelposadj < 5.0) {
    1008                 $r *= $this->ilabelposadj;
    1009             }
    1010 
    1011             $r += $img->GetFontHeight()/1.5;
    1012 
    1013             $xt=round($r*cos($a)+$xc);
    1014             $yt=round($yc-$r*sin($a));
    1015 
    1016             // Normalize angle
    1017             while( $a < 0 ) $a += 2*M_PI;
    1018             while( $a > 2*M_PI ) $a -= 2*M_PI;
    1019 
    1020             if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0;
    1021             if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI;
    1022             if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1;
    1023             if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI);
    1024 
    1025             if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI;
    1026             if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI);
    1027             if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1;
    1028             if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI);
    1029             if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0;
    1030 
    1031             $this->value->Stroke($img,$label,$xt-$dx*$w,$yt-$dy*$h);
    1032         }
    1033     }
    1034 
    1035     function UsePlotThemeColors($flag = true) {
    1036         $this->use_plot_theme_colors = $flag;
    1037     }
     949        // Default value
     950        if( $this->ilabelposadj === 'auto' )
     951            $this->ilabelposadj = 0.65;
     952
     953        // We position the values diferently depending on if they are inside
     954        // or outside the pie
     955        if( $this->ilabelposadj < 1.0 ) {
     956
     957            $this->value->SetAlign('center','center');
     958            $this->value->margin = 0;
     959           
     960            $xt=round($this->ilabelposadj*$r*cos($a)+$xc);
     961            $yt=round($yc-$this->ilabelposadj*$r*sin($a));
     962           
     963            $this->value->Stroke($img,$label,$xt,$yt);
     964        }
     965        else {
     966
     967            $this->value->halign = "left";
     968            $this->value->valign = "top";
     969            $this->value->margin = 0;
     970                   
     971            // Position the axis title.
     972            // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
     973            // that intersects with the extension of the corresponding axis. The code looks a little
     974            // bit messy but this is really the only way of having a reasonable position of the
     975            // axis titles.
     976            $this->value->ApplyFont($img);
     977            $h=$img->GetTextHeight($label);
     978            // For numeric values the format of the display value
     979            // must be taken into account
     980            if( is_numeric($label) ) {
     981                if( $label > 0 )
     982                    $w=$img->GetTextWidth(sprintf($this->value->format,$label));
     983                else
     984                    $w=$img->GetTextWidth(sprintf($this->value->negformat,$label));
     985            }
     986            else
     987                $w=$img->GetTextWidth($label);
     988
     989            if( $this->ilabelposadj > 1.0 && $this->ilabelposadj < 5.0) {
     990                $r *= $this->ilabelposadj;
     991            }
     992           
     993            $r += $img->GetFontHeight()/1.5;
     994
     995            $xt=round($r*cos($a)+$xc);
     996            $yt=round($yc-$r*sin($a));
     997
     998            // Normalize angle
     999            while( $a < 0 ) $a += 2*M_PI;
     1000            while( $a > 2*M_PI ) $a -= 2*M_PI;
     1001
     1002            if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0;
     1003            if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI;
     1004            if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1;
     1005            if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI);
     1006           
     1007            if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI;
     1008            if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI);
     1009            if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1;
     1010            if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI);
     1011            if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0;
     1012           
     1013            $this->value->Stroke($img,$label,$xt-$dx*$w,$yt-$dy*$h);
     1014        }
     1015    }   
    10381016} // Class
    10391017
     
    10411019//===================================================
    10421020// CLASS PiePlotC
    1043 // Description: Same as a normal pie plot but with a
     1021// Description: Same as a normal pie plot but with a 
    10441022// filled circle in the center
    10451023//===================================================
    10461024class PiePlotC extends PiePlot {
    1047     private $imidsize=0.5;  // Fraction of total width
     1025    private $imidsize=0.5;              // Fraction of total width
    10481026    private $imidcolor='white';
    10491027    public $midtitle='';
    10501028    private $middlecsimtarget='',$middlecsimwintarget='',$middlecsimalt='';
    10511029
    1052     function __construct($data,$aCenterTitle='') {
    1053         parent::__construct($data);
    1054         $this->midtitle = new Text();
    1055         $this->midtitle->ParagraphAlign('center');
     1030    function PiePlotC($data,$aCenterTitle='') {
     1031        parent::PiePlot($data);
     1032        $this->midtitle = new Text();
     1033        $this->midtitle->ParagraphAlign('center');
    10561034    }
    10571035
    10581036    function SetMid($aTitle,$aColor='white',$aSize=0.5) {
    1059         $this->midtitle->Set($aTitle);
    1060 
    1061         $this->imidsize = $aSize ;
    1062         $this->imidcolor = $aColor ;
     1037        $this->midtitle->Set($aTitle);
     1038
     1039        $this->imidsize = $aSize ;
     1040        $this->imidcolor = $aColor ;
    10631041    }
    10641042
    10651043    function SetMidTitle($aTitle) {
    1066         $this->midtitle->Set($aTitle);
     1044        $this->midtitle->Set($aTitle);
    10671045    }
    10681046
    10691047    function SetMidSize($aSize) {
    1070         $this->imidsize = $aSize ;
     1048        $this->imidsize = $aSize ;
    10711049    }
    10721050
    10731051    function SetMidColor($aColor) {
    1074         $this->imidcolor = $aColor ;
     1052        $this->imidcolor = $aColor ;
    10751053    }
    10761054
    10771055    function SetMidCSIM($aTarget,$aAlt='',$aWinTarget='') {
    1078         $this->middlecsimtarget = $aTarget;
    1079         $this->middlecsimwintarget = $aWinTarget;
    1080         $this->middlecsimalt = $aAlt;
    1081     }
    1082 
    1083     function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {
     1056        $this->middlecsimtarget = $aTarget;
     1057        $this->middlecsimwintarget = $aWinTarget;
     1058        $this->middlecsimalt = $aAlt;
     1059    }
     1060
     1061    function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { 
    10841062        //Slice number, ellipse centre (x,y), radius, start angle, end angle
    1085         while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
    1086         while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
    1087 
    1088         $sa = 2*M_PI - $sa;
    1089         $ea = 2*M_PI - $ea;
    1090 
    1091         // Special case when we have only one slice since then both start and end
    1092         // angle will be == 0
    1093         if( abs($sa - $ea) < 0.0001 ) {
    1094             $sa=2*M_PI; $ea=0;
    1095         }
    1096 
    1097         // Add inner circle first point
    1098         $xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
    1099         $yp = floor($yc-($this->imidsize*$radius*sin($ea)));
    1100         $coords = "$xp, $yp";
    1101 
    1102         //add coordinates every 0.25 radians
    1103         $a=$ea+0.25;
    1104 
    1105         // If we cross the 360-limit with a slice we need to handle
    1106         // the fact that end angle is smaller than start
    1107         if( $sa < $ea ) {
    1108             while ($a <= 2*M_PI) {
    1109                 $xp = floor($radius*cos($a)+$xc);
    1110                 $yp = floor($yc-$radius*sin($a));
    1111                 $coords.= ", $xp, $yp";
    1112                 $a += 0.25;
    1113             }
    1114             $a -= 2*M_PI;
    1115         }
    1116 
    1117         while ($a < $sa) {
    1118             $xp = floor(($this->imidsize*$radius*cos($a)+$xc));
    1119             $yp = floor($yc-($this->imidsize*$radius*sin($a)));
    1120             $coords.= ", $xp, $yp";
    1121             $a += 0.25;
    1122         }
    1123 
    1124         // Make sure we end at the last point
    1125         $xp = floor(($this->imidsize*$radius*cos($sa)+$xc));
    1126         $yp = floor($yc-($this->imidsize*$radius*sin($sa)));
    1127         $coords.= ", $xp, $yp";
    1128 
    1129         // Straight line to outer circle
    1130         $xp = floor($radius*cos($sa)+$xc);
    1131         $yp = floor($yc-$radius*sin($sa));
    1132         $coords.= ", $xp, $yp";
    1133 
    1134         //add coordinates every 0.25 radians
    1135         $a=$sa - 0.25;
    1136         while ($a > $ea) {
    1137             $xp = floor($radius*cos($a)+$xc);
    1138             $yp = floor($yc-$radius*sin($a));
    1139             $coords.= ", $xp, $yp";
    1140             $a -= 0.25;
    1141         }
    1142 
    1143         //Add the last point on the arc
    1144         $xp = floor($radius*cos($ea)+$xc);
    1145         $yp = floor($yc-$radius*sin($ea));
    1146         $coords.= ", $xp, $yp";
    1147 
    1148         // Close the arc
    1149         $xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
    1150         $yp = floor($yc-($this->imidsize*$radius*sin($ea)));
    1151         $coords .= ", $xp, $yp";
    1152 
    1153         if( !empty($this->csimtargets[$i]) ) {
    1154             $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".
    1155             $this->csimtargets[$i]."\"";
    1156             if( !empty($this->csimwintargets[$i]) ) {
    1157                 $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
    1158             }
    1159             if( !empty($this->csimalts[$i]) ) {
    1160                 $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
    1161                 $this->csimareas .= " title=\"$tmp\"  alt=\"$tmp\" ";
    1162             }
    1163             $this->csimareas .= " />\n";
    1164         }
     1063        while( $sa > 2*M_PI ) $sa = $sa - 2*M_PI;
     1064        while( $ea > 2*M_PI ) $ea = $ea - 2*M_PI;
     1065
     1066        $sa = 2*M_PI - $sa;
     1067        $ea = 2*M_PI - $ea;
     1068
     1069        // Special case when we have only one slice since then both start and end
     1070        // angle will be == 0
     1071        if( abs($sa - $ea) < 0.0001 ) {
     1072            $sa=2*M_PI; $ea=0;
     1073        }
     1074
     1075        // Add inner circle first point
     1076        $xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
     1077        $yp = floor($yc-($this->imidsize*$radius*sin($ea)));
     1078        $coords = "$xp, $yp";
     1079       
     1080        //add coordinates every 0.25 radians
     1081        $a=$ea+0.25;
     1082
     1083        // If we cross the 360-limit with a slice we need to handle
     1084        // the fact that end angle is smaller than start
     1085        if( $sa < $ea ) {
     1086            while ($a <= 2*M_PI) {
     1087                $xp = floor($radius*cos($a)+$xc);
     1088                $yp = floor($yc-$radius*sin($a));
     1089                $coords.= ", $xp, $yp";
     1090                $a += 0.25;
     1091            }
     1092            $a -= 2*M_PI;
     1093        }
     1094
     1095        while ($a < $sa) {
     1096            $xp = floor(($this->imidsize*$radius*cos($a)+$xc));
     1097            $yp = floor($yc-($this->imidsize*$radius*sin($a)));
     1098            $coords.= ", $xp, $yp";
     1099            $a += 0.25;
     1100        }
     1101
     1102        // Make sure we end at the last point
     1103        $xp = floor(($this->imidsize*$radius*cos($sa)+$xc));
     1104        $yp = floor($yc-($this->imidsize*$radius*sin($sa)));
     1105        $coords.= ", $xp, $yp";
     1106
     1107        // Straight line to outer circle
     1108        $xp = floor($radius*cos($sa)+$xc);
     1109        $yp = floor($yc-$radius*sin($sa));
     1110        $coords.= ", $xp, $yp";
     1111
     1112        //add coordinates every 0.25 radians
     1113        $a=$sa - 0.25;
     1114        while ($a > $ea) {
     1115            $xp = floor($radius*cos($a)+$xc);
     1116            $yp = floor($yc-$radius*sin($a));
     1117            $coords.= ", $xp, $yp";
     1118            $a -= 0.25;
     1119        }
     1120               
     1121        //Add the last point on the arc
     1122        $xp = floor($radius*cos($ea)+$xc);
     1123        $yp = floor($yc-$radius*sin($ea));
     1124        $coords.= ", $xp, $yp";
     1125
     1126        // Close the arc
     1127        $xp = floor(($this->imidsize*$radius*cos($ea))+$xc);
     1128        $yp = floor($yc-($this->imidsize*$radius*sin($ea)));
     1129        $coords .= ", $xp, $yp";
     1130
     1131        if( !empty($this->csimtargets[$i]) ) {
     1132            $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".
     1133                $this->csimtargets[$i]."\"";
     1134            if( !empty($this->csimwintargets[$i]) ) {
     1135                $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
     1136            }
     1137            if( !empty($this->csimalts[$i]) ) {
     1138                $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
     1139                $this->csimareas .= " title=\"$tmp\"  alt=\"$tmp\" ";
     1140            }
     1141            $this->csimareas .= " />\n";
     1142        }
    11651143    }
    11661144
     
    11681146    function Stroke($img,$aaoption=0) {
    11691147
    1170         // Stroke the pie but don't stroke values
    1171         $tmp =  $this->value->show;
    1172         $this->value->show = false;
    1173         parent::Stroke($img,$aaoption);
    1174         $this->value->show = $tmp;
    1175 
    1176         $xc = round($this->posx*$img->width);
    1177         $yc = round($this->posy*$img->height);
    1178 
    1179         $radius = floor($this->radius * min($img->width,$img->height)) ;
    1180 
    1181 
    1182         if( $this->imidsize > 0 && $aaoption !== 2 ) {
    1183 
    1184             if( $this->ishadowcolor != "" ) {
    1185                 $img->SetColor($this->ishadowcolor);
    1186                 $img->FilledCircle($xc+$this->ishadowdrop,$yc+$this->ishadowdrop,
    1187                 round($radius*$this->imidsize));
    1188             }
    1189 
    1190             $img->SetColor($this->imidcolor);
    1191             $img->FilledCircle($xc,$yc,round($radius*$this->imidsize));
    1192 
    1193             if(  $this->pie_border && $aaoption === 0 ) {
    1194                 $img->SetColor($this->color);
    1195                 $img->Circle($xc,$yc,round($radius*$this->imidsize));
    1196             }
    1197 
    1198             if( !empty($this->middlecsimtarget) )
    1199             $this->AddMiddleCSIM($xc,$yc,round($radius*$this->imidsize));
    1200 
    1201         }
    1202 
    1203         if( $this->value->show && $aaoption !== 1) {
    1204             $this->StrokeAllLabels($img,$xc,$yc,$radius);
    1205             $this->midtitle->SetPos($xc,$yc,'center','center');
    1206             $this->midtitle->Stroke($img);
    1207         }
     1148        // Stroke the pie but don't stroke values
     1149        $tmp =  $this->value->show;
     1150        $this->value->show = false;
     1151        parent::Stroke($img,$aaoption);
     1152        $this->value->show = $tmp;
     1153
     1154        $xc = round($this->posx*$img->width);
     1155        $yc = round($this->posy*$img->height);
     1156
     1157        $radius = floor($this->radius * min($img->width,$img->height)) ;
     1158
     1159
     1160        if( $this->imidsize > 0 && $aaoption !== 2 ) {
     1161
     1162            if( $this->ishadowcolor != "" ) {
     1163                $img->SetColor($this->ishadowcolor);
     1164                $img->FilledCircle($xc+$this->ishadowdrop,$yc+$this->ishadowdrop,
     1165                                   round($radius*$this->imidsize));
     1166            }
     1167
     1168            $img->SetColor($this->imidcolor);
     1169            $img->FilledCircle($xc,$yc,round($radius*$this->imidsize));
     1170
     1171            if(  $this->pie_border && $aaoption === 0 ) {
     1172                $img->SetColor($this->color);
     1173                $img->Circle($xc,$yc,round($radius*$this->imidsize));
     1174            }
     1175
     1176            if( !empty($this->middlecsimtarget) )
     1177                $this->AddMiddleCSIM($xc,$yc,round($radius*$this->imidsize));
     1178
     1179        }
     1180
     1181        if( $this->value->show && $aaoption !== 1) {
     1182            $this->StrokeAllLabels($img,$xc,$yc,$radius);
     1183            $this->midtitle->SetPos($xc,$yc,'center','center');
     1184            $this->midtitle->Stroke($img);
     1185        }
    12081186
    12091187    }
    12101188
    12111189    function AddMiddleCSIM($xc,$yc,$r) {
    1212         $xc=round($xc);$yc=round($yc);$r=round($r);
    1213         $this->csimareas .= "<area shape=\"circle\" coords=\"$xc,$yc,$r\" href=\"".
    1214         $this->middlecsimtarget."\"";
    1215         if( !empty($this->middlecsimwintarget) ) {
    1216             $this->csimareas .= " target=\"".$this->middlecsimwintarget."\"";
    1217         }
    1218         if( !empty($this->middlecsimalt) ) {
    1219             $tmp = $this->middlecsimalt;
    1220             $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
    1221         }
    1222         $this->csimareas .= " />\n";
     1190        $xc=round($xc);$yc=round($yc);$r=round($r);
     1191        $this->csimareas .= "<area shape=\"circle\" coords=\"$xc,$yc,$r\" href=\"".
     1192            $this->middlecsimtarget."\"";
     1193        if( !empty($this->middlecsimwintarget) ) {
     1194            $this->csimareas .= " target=\"".$this->middlecsimwintarget."\"";
     1195        }
     1196        if( !empty($this->middlecsimalt) ) {
     1197            $tmp = $this->middlecsimalt;
     1198            $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
     1199        }
     1200        $this->csimareas .= " />\n";
    12231201    }
    12241202
    12251203    function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
    12261204
    1227         if( $this->ilabelposadj === 'auto' )
    1228         $this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize;
    1229 
    1230         parent::StrokeLabel($label,$img,$xc,$yc,$a,$r);
     1205        if( $this->ilabelposadj === 'auto' )
     1206            $this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize;
     1207
     1208        parent::StrokeLabel($label,$img,$xc,$yc,$a,$r);
    12311209
    12321210    }
     
    12371215//===================================================
    12381216// CLASS PieGraph
    1239 // Description:
     1217// Description: 
    12401218//===================================================
    12411219class PieGraph extends Graph {
    1242     private $posx, $posy, $radius;
    1243     private $legends=array();
     1220    private $posx, $posy, $radius;             
     1221    private $legends=array();   
    12441222    public $plots=array();
    12451223    public $pieaa = false ;
    1246     //---------------
    1247     // CONSTRUCTOR
    1248     function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) {
    1249         parent::__construct($width,$height,$cachedName,$timeout,$inline);
    1250         $this->posx=$width/2;
    1251         $this->posy=$height/2;
    1252         $this->SetColor(array(255,255,255));
    1253 
    1254         if ($this->graph_theme) {
    1255           $this->graph_theme->ApplyGraph($this);
    1256         }
    1257     }
    1258 
    1259     //---------------
    1260     // PUBLIC METHODS
     1224//---------------
     1225// CONSTRUCTOR
     1226    function PieGraph($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) {
     1227        $this->Graph($width,$height,$cachedName,$timeout,$inline);
     1228        $this->posx=$width/2;
     1229        $this->posy=$height/2;
     1230        $this->SetColor(array(255,255,255));           
     1231    }
     1232
     1233//---------------
     1234// PUBLIC METHODS       
    12611235    function Add($aObj) {
    12621236
    1263         if( is_array($aObj) && count($aObj) > 0 )
    1264         $cl = $aObj[0];
    1265         else
    1266         $cl = $aObj;
    1267 
    1268         if( $cl instanceof Text )
    1269         $this->AddText($aObj);
    1270         elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) )
    1271         $this->AddIcon($aObj);
    1272         else {
    1273             if( is_array($aObj) ) {
    1274                 $n = count($aObj);
    1275                 for($i=0; $i < $n; ++$i ) {
    1276                     //if ($aObj[$i]->theme) {
    1277                     //    $this->ClearTheme();
    1278                     //}
    1279                     $this->plots[] = $aObj[$i];
    1280                 }
    1281             }
    1282             else {
    1283                 //if ($aObj->theme) {
    1284                 //    $this->ClearTheme();
    1285                 //}
    1286                 $this->plots[] = $aObj;
    1287             }
    1288         }
    1289 
    1290         if ($this->graph_theme) {
    1291             $this->graph_theme->SetupPlot($aObj);
    1292             if ($aObj->is_using_plot_theme) {
    1293                 $aObj->UsePlotThemeColors();
    1294             }
    1295         }
     1237        if( is_array($aObj) && count($aObj) > 0 )
     1238            $cl = $aObj[0];
     1239        else
     1240            $cl = $aObj;
     1241
     1242        if( $cl instanceof Text )
     1243            $this->AddText($aObj);
     1244        elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) )
     1245            $this->AddIcon($aObj);
     1246        else {
     1247            if( is_array($aObj) ) {
     1248                $n = count($aObj);
     1249                for($i=0; $i < $n; ++$i ) {
     1250                    $this->plots[] = $aObj[$i];
     1251                }
     1252            }
     1253            else {
     1254                $this->plots[] = $aObj;
     1255            }
     1256        }
    12961257    }
    12971258
    12981259    function SetAntiAliasing($aFlg=true) {
    1299         $this->pieaa = $aFlg;
    1300     }
    1301 
     1260        $this->pieaa = $aFlg;
     1261    }
     1262       
    13021263    function SetColor($c) {
    1303         $this->SetMarginColor($c);
     1264        $this->SetMarginColor($c);
    13041265    }
    13051266
    13061267
    13071268    function DisplayCSIMAreas() {
    1308         $csim="";
    1309         foreach($this->plots as $p ) {
    1310             $csim .= $p->GetCSIMareas();
    1311         }
    1312        
    1313         $csim.= $this->legend->GetCSIMareas();
    1314         if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) {
    1315             $this->img->SetColor($this->csimcolor);
    1316             $n = count($coords[0]);
    1317             for ($i=0; $i < $n; $i++) {
    1318                 if ($coords[1][$i]=="poly") {
    1319                     preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts);
    1320                     $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]);
    1321                     $m = count($pts[0]);
    1322                     for ($j=0; $j < $m; $j++) {
    1323                         $this->img->LineTo($pts[1][$j],$pts[2][$j]);
    1324                     }
    1325                 } else if ($coords[1][$i]=="rect") {
    1326                     $pts = preg_split('/,/', $coords[2][$i]);
    1327                     $this->img->SetStartPoint($pts[0],$pts[1]);
    1328                     $this->img->LineTo($pts[2],$pts[1]);
    1329                     $this->img->LineTo($pts[2],$pts[3]);
    1330                     $this->img->LineTo($pts[0],$pts[3]);
    1331                     $this->img->LineTo($pts[0],$pts[1]);
    1332 
    1333                 }
    1334             }
    1335         }
     1269            $csim="";
     1270            foreach($this->plots as $p ) {
     1271                $csim .= $p->GetCSIMareas();
     1272            }
     1273            //$csim.= $this->legend->GetCSIMareas();
     1274            if (preg_match_all("/area shape=\"(\w+)\" coords=\"([0-9\, ]+)\"/", $csim, $coords)) {
     1275                $this->img->SetColor($this->csimcolor);
     1276                $n = count($coords[0]);
     1277                for ($i=0; $i < $n; $i++) {
     1278                    if ($coords[1][$i]=="poly") {
     1279                        preg_match_all('/\s*([0-9]+)\s*,\s*([0-9]+)\s*,*/',$coords[2][$i],$pts);
     1280                        $this->img->SetStartPoint($pts[1][count($pts[0])-1],$pts[2][count($pts[0])-1]);
     1281                        $m = count($pts[0]);
     1282                        for ($j=0; $j < $m; $j++) {
     1283                            $this->img->LineTo($pts[1][$j],$pts[2][$j]);
     1284                        }
     1285                    } else if ($coords[1][$i]=="rect") {
     1286                        $pts = preg_split('/,/', $coords[2][$i]);
     1287                        $this->img->SetStartPoint($pts[0],$pts[1]);
     1288                        $this->img->LineTo($pts[2],$pts[1]);
     1289                        $this->img->LineTo($pts[2],$pts[3]);
     1290                        $this->img->LineTo($pts[0],$pts[3]);
     1291                        $this->img->LineTo($pts[0],$pts[1]);
     1292                                               
     1293                    }
     1294                }
     1295            }
    13361296    }
    13371297
    13381298    // Method description
    13391299    function Stroke($aStrokeFileName="") {
    1340 
    1341         // If the filename is the predefined value = '_csim_special_'
    1342         // we assume that the call to stroke only needs to do enough
    1343         // to correctly generate the CSIM maps.
    1344         // We use this variable to skip things we don't strictly need
    1345         // to do to generate the image map to improve performance
    1346         // a best we can. Therefor you will see a lot of tests !$_csim in the
    1347         // code below.
    1348         $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
    1349 
    1350         // If we are called the second time (perhaps the user has called GetHTMLImageMap()
    1351         // himself then the legends have alsready been populated once in order to get the
    1352         // CSIM coordinats. Since we do not want the legends to be populated a second time
    1353         // we clear the legends
    1354         $this->legend->Clear();
    1355 
    1356         // We need to know if we have stroked the plot in the
    1357         // GetCSIMareas. Otherwise the CSIM hasn't been generated
    1358         // and in the case of GetCSIM called before stroke to generate
    1359         // CSIM without storing an image to disk GetCSIM must call Stroke.
    1360         $this->iHasStroked = true;
    1361 
    1362         $n = count($this->plots);
    1363 
    1364         if( $this->pieaa ) {
    1365 
    1366             if( !$_csim ) {
    1367                 if( $this->background_image != "" ) {
    1368                     $this->StrokeFrameBackground();
    1369                 }
    1370                 else {
    1371                     $this->StrokeFrame();
    1372                     $this->StrokeBackgroundGrad();
    1373                 }
    1374             }
    1375 
    1376 
    1377             $w = $this->img->width;
    1378             $h = $this->img->height;
    1379             $oldimg = $this->img->img;
    1380 
    1381             $this->img->CreateImgCanvas(2*$w,2*$h);
    1382 
    1383             $this->img->SetColor( $this->margin_color );
    1384             $this->img->FilledRectangle(0,0,2*$w-1,2*$h-1);
    1385 
    1386             // Make all icons *2 i size since we will be scaling down the
    1387             // imahe to do the anti aliasing
    1388             $ni = count($this->iIcons);
    1389             for($i=0; $i < $ni; ++$i) {
    1390                 $this->iIcons[$i]->iScale *= 2 ;
    1391                 if( $this->iIcons[$i]->iX > 1 )
    1392                 $this->iIcons[$i]->iX *= 2 ;
    1393                 if( $this->iIcons[$i]->iY > 1 )
    1394                 $this->iIcons[$i]->iY *= 2 ;
    1395             }
    1396 
    1397             $this->StrokeIcons();
    1398 
    1399             for($i=0; $i < $n; ++$i) {
    1400                 if( $this->plots[$i]->posx > 1 )
    1401                 $this->plots[$i]->posx *= 2 ;
    1402                 if( $this->plots[$i]->posy > 1 )
    1403                 $this->plots[$i]->posy *= 2 ;
    1404 
    1405                 $this->plots[$i]->Stroke($this->img,1);
    1406 
    1407                 if( $this->plots[$i]->posx > 1 )
    1408                 $this->plots[$i]->posx /= 2 ;
    1409                 if( $this->plots[$i]->posy > 1 )
    1410                 $this->plots[$i]->posy /= 2 ;
    1411             }
    1412 
    1413             $indent = $this->doframe ? ($this->frame_weight + ($this->doshadow ? $this->shadow_width : 0 )) : 0 ;
    1414             $indent += $this->framebevel ? $this->framebeveldepth + 1 : 0 ;
    1415             $this->img->CopyCanvasH($oldimg,$this->img->img,$indent,$indent,$indent,$indent,
    1416             $w-2*$indent,$h-2*$indent,2*($w-$indent),2*($h-$indent));
    1417 
    1418             $this->img->img = $oldimg ;
    1419             $this->img->width = $w ;
    1420             $this->img->height = $h ;
    1421 
    1422             for($i=0; $i < $n; ++$i) {
    1423                 $this->plots[$i]->Stroke($this->img,2); // Stroke labels
    1424                 $this->plots[$i]->Legend($this);
    1425             }
    1426 
    1427         }
    1428         else {
    1429 
    1430             if( !$_csim ) {
    1431                 if( $this->background_image != "" ) {
    1432                     $this->StrokeFrameBackground();
    1433                 }
    1434                 else {
    1435                     $this->StrokeFrame();
    1436                     $this->StrokeBackgroundGrad();
    1437                 }
    1438             }
    1439 
    1440             $this->StrokeIcons();
    1441 
    1442             for($i=0; $i < $n; ++$i) {
    1443                 $this->plots[$i]->Stroke($this->img);
    1444                 $this->plots[$i]->Legend($this);
    1445             }
    1446         }
    1447 
    1448         $this->legend->Stroke($this->img);
    1449         $this->footer->Stroke($this->img);
    1450         $this->StrokeTitles();
    1451 
    1452         if( !$_csim ) {
    1453 
    1454             // Stroke texts
    1455             if( $this->texts != null ) {
    1456                 $n = count($this->texts);
    1457                 for($i=0; $i < $n; ++$i ) {
    1458                     $this->texts[$i]->Stroke($this->img);
    1459                 }
    1460             }
    1461 
    1462             if( _JPG_DEBUG ) {
    1463                 $this->DisplayCSIMAreas();
    1464             }
    1465 
    1466             // Should we do any final image transformation
    1467             if( $this->iImgTrans ) {
    1468                 if( !class_exists('ImgTrans',false) ) {
    1469                     require_once('jpgraph_imgtrans.php');
    1470                     //JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.');
    1471                 }
    1472 
    1473                 $tform = new ImgTrans($this->img->img);
    1474                 $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
    1475                 $this->iImgTransDirection,$this->iImgTransHighQ,
    1476                 $this->iImgTransMinSize,$this->iImgTransFillColor,
    1477                 $this->iImgTransBorder);
    1478             }
    1479 
    1480 
    1481             // If the filename is given as the special "__handle"
    1482             // then the image handler is returned and the image is NOT
    1483             // streamed back
    1484             if( $aStrokeFileName == _IMG_HANDLER ) {
    1485                 return $this->img->img;
    1486             }
    1487             else {
    1488                 // Finally stream the generated picture
    1489                 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
    1490                 $aStrokeFileName);
    1491             }
    1492         }
     1300        // If the filename is the predefined value = '_csim_special_'
     1301        // we assume that the call to stroke only needs to do enough
     1302        // to correctly generate the CSIM maps.
     1303        // We use this variable to skip things we don't strictly need
     1304        // to do to generate the image map to improve performance
     1305        // a best we can. Therefor you will see a lot of tests !$_csim in the
     1306        // code below.
     1307        $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
     1308
     1309        // We need to know if we have stroked the plot in the
     1310        // GetCSIMareas. Otherwise the CSIM hasn't been generated
     1311        // and in the case of GetCSIM called before stroke to generate
     1312        // CSIM without storing an image to disk GetCSIM must call Stroke.
     1313        $this->iHasStroked = true;
     1314
     1315        $n = count($this->plots);
     1316
     1317        if( $this->pieaa ) {
     1318
     1319            if( !$_csim ) {
     1320                if( $this->background_image != "" ) {
     1321                    $this->StrokeFrameBackground();             
     1322                }
     1323                else {
     1324                    $this->StrokeFrame();               
     1325                    $this->StrokeBackgroundGrad();
     1326                }
     1327            }
     1328
     1329
     1330            $w = $this->img->width;
     1331            $h = $this->img->height;
     1332            $oldimg = $this->img->img;
     1333
     1334            $this->img->CreateImgCanvas(2*$w,2*$h);
     1335           
     1336            $this->img->SetColor( $this->margin_color );
     1337            $this->img->FilledRectangle(0,0,2*$w-1,2*$h-1);
     1338
     1339            // Make all icons *2 i size since we will be scaling down the
     1340            // imahe to do the anti aliasing
     1341            $ni = count($this->iIcons);
     1342            for($i=0; $i < $ni; ++$i) {
     1343                $this->iIcons[$i]->iScale *= 2 ;
     1344                if( $this->iIcons[$i]->iX > 1 )
     1345                    $this->iIcons[$i]->iX *= 2 ;
     1346                if( $this->iIcons[$i]->iY > 1 )
     1347                    $this->iIcons[$i]->iY *= 2 ;
     1348            }
     1349
     1350            $this->StrokeIcons();
     1351
     1352            for($i=0; $i < $n; ++$i) {
     1353                if( $this->plots[$i]->posx > 1 )
     1354                    $this->plots[$i]->posx *= 2 ;
     1355                if( $this->plots[$i]->posy > 1 )
     1356                    $this->plots[$i]->posy *= 2 ;
     1357
     1358                $this->plots[$i]->Stroke($this->img,1);
     1359
     1360                if( $this->plots[$i]->posx > 1 )
     1361                    $this->plots[$i]->posx /= 2 ;
     1362                if( $this->plots[$i]->posy > 1 )
     1363                    $this->plots[$i]->posy /= 2 ;
     1364            }
     1365
     1366            $indent = $this->doframe ? ($this->frame_weight + ($this->doshadow ? $this->shadow_width : 0 )) : 0 ;
     1367            $indent += $this->framebevel ? $this->framebeveldepth + 1 : 0 ;
     1368            $this->img->CopyCanvasH($oldimg,$this->img->img,$indent,$indent,$indent,$indent,
     1369                                    $w-2*$indent,$h-2*$indent,2*($w-$indent),2*($h-$indent));
     1370
     1371            $this->img->img = $oldimg ;
     1372            $this->img->width = $w ;
     1373            $this->img->height = $h ;
     1374
     1375            for($i=0; $i < $n; ++$i) {
     1376                $this->plots[$i]->Stroke($this->img,2); // Stroke labels
     1377                $this->plots[$i]->Legend($this);
     1378            }
     1379
     1380        }
     1381        else {
     1382
     1383            if( !$_csim ) {
     1384                if( $this->background_image != "" ) {
     1385                    $this->StrokeFrameBackground();             
     1386                }
     1387                else {
     1388                    $this->StrokeFrame();               
     1389                }
     1390            }
     1391
     1392            $this->StrokeIcons();
     1393
     1394            for($i=0; $i < $n; ++$i) {
     1395                $this->plots[$i]->Stroke($this->img);
     1396                $this->plots[$i]->Legend($this);
     1397            }
     1398        }
     1399
     1400        $this->legend->Stroke($this->img);
     1401        $this->footer->Stroke($this->img);
     1402        $this->StrokeTitles();
     1403
     1404        if( !$_csim ) {
     1405
     1406            // Stroke texts
     1407            if( $this->texts != null ) {
     1408                $n = count($this->texts);
     1409                for($i=0; $i < $n; ++$i ) {
     1410                    $this->texts[$i]->Stroke($this->img);
     1411                }
     1412            }
     1413
     1414            if( _JPG_DEBUG ) {
     1415                $this->DisplayCSIMAreas();
     1416            }
     1417
     1418            // Should we do any final image transformation
     1419            if( $this->iImgTrans ) {
     1420                if( !class_exists('ImgTrans',false) ) {
     1421                    require_once('jpgraph_imgtrans.php');
     1422                    //JpGraphError::Raise('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.');
     1423                }
     1424               
     1425                $tform = new ImgTrans($this->img->img);
     1426                $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
     1427                                                 $this->iImgTransDirection,$this->iImgTransHighQ,
     1428                                                 $this->iImgTransMinSize,$this->iImgTransFillColor,
     1429                                                 $this->iImgTransBorder);
     1430            }
     1431
     1432
     1433            // If the filename is given as the special "__handle"
     1434            // then the image handler is returned and the image is NOT
     1435            // streamed back
     1436            if( $aStrokeFileName == _IMG_HANDLER ) {
     1437                return $this->img->img;
     1438            }
     1439            else {
     1440                // Finally stream the generated picture                                 
     1441                $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
     1442                                           $aStrokeFileName);           
     1443            }
     1444        }
    14931445    }
    14941446} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_pie3d.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_PIE3D.PHP
    4  // Description: 3D Pie plot extension for JpGraph
    5  // Created:     2001-03-24
    6  // Ver:         $Id: jpgraph_pie3d.php 1329 2009-06-20 19:23:30Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_PIE3D.PHP
     4// Description: 3D Pie plot extension for JpGraph
     5// Created:     2001-03-24
     6// Ver:         $Id: jpgraph_pie3d.php 956 2007-11-17 13:19:20Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212//===================================================
    1313// CLASS PiePlot3D
    14 // Description: Plots a 3D pie with a specified projection
     14// Description: Plots a 3D pie with a specified projection 
    1515// angle between 20 and 70 degrees.
    1616//===================================================
    1717class PiePlot3D extends PiePlot {
    1818    private $labelhintcolor="red",$showlabelhint=true;
    19     private $angle=50;
     19    private $angle=50; 
    2020    private $edgecolor="", $edgeweight=1;
    2121    private $iThickness=false;
    22 
    23     //---------------
    24     // CONSTRUCTOR
    25     function __construct($data) {
    26         $this->radius = 0.5;
    27         $this->data = $data;
    28         $this->title = new Text("");
    29         $this->title->SetFont(FF_FONT1,FS_BOLD);
    30         $this->value = new DisplayValue();
    31         $this->value->Show();
    32         $this->value->SetFormat('%.0f%%');
    33     }
    34 
    35     //---------------
    36     // PUBLIC METHODS
    37 
     22       
     23//---------------
     24// CONSTRUCTOR
     25    function PiePlot3d($data) {
     26        $this->radius = 0.5;
     27        $this->data = $data;
     28        $this->title = new Text("");
     29        $this->title->SetFont(FF_FONT1,FS_BOLD);
     30        $this->value = new DisplayValue();
     31        $this->value->Show();
     32        $this->value->SetFormat('%.0f%%');
     33    }
     34
     35//---------------
     36// PUBLIC METHODS       
     37       
    3838    // Set label arrays
    3939    function SetLegends($aLegend) {
    40         $this->legends = array_reverse(array_slice($aLegend,0,count($this->data)));
     40        $this->legends = array_reverse(array_slice($aLegend,0,count($this->data)));
    4141    }
    4242
    4343    function SetSliceColors($aColors) {
    44         $this->setslicecolors = $aColors;
     44        $this->setslicecolors = $aColors;
    4545    }
    4646
    4747    function Legend($aGraph) {
    48         parent::Legend($aGraph);
    49         $aGraph->legend->txtcol = array_reverse($aGraph->legend->txtcol);
     48        parent::Legend($aGraph);
     49        $aGraph->legend->txtcol = array_reverse($aGraph->legend->txtcol);
    5050    }
    5151
    5252    function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') {
    53         $this->csimtargets = $aTargets;
    54         $this->csimwintargets = $aWinTargets;
    55         $this->csimalts = $aAlts;
     53        $this->csimtargets = $aTargets;
     54        $this->csimwintargets = $aWinTargets;
     55        $this->csimalts = $aAlts;
    5656    }
    5757
     
    5959    // will be used to separate pie slices.
    6060    function SetEdge($aColor='black',$aWeight=1) {
    61         $this->edgecolor = $aColor;
    62         $this->edgeweight = $aWeight;
     61        $this->edgecolor = $aColor;
     62        $this->edgeweight = $aWeight;
     63    }
     64
     65    // Dummy function to make Pie3D behave in a similair way to 2D
     66    function ShowBorder($exterior=true,$interior=true) {
     67        JpGraphError::RaiseL(14001);
     68//('Pie3D::ShowBorder() . Deprecated function. Use Pie3D::SetEdge() to control the edges around slices.');
    6369    }
    6470
     
    6672    // Must be between 20 and 70 degrees
    6773    function SetAngle($a) {
    68         if( $a<5 || $a>90 ) {
    69             JpGraphError::RaiseL(14002);
    70             //("PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees.");
    71         }
    72         else {
    73             $this->angle = $a;
    74         }
     74        if( $a<5 || $a>90 )
     75            JpGraphError::RaiseL(14002);
     76//("PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees.");
     77        else
     78            $this->angle = $a;
    7579    }
    7680
    7781    function Add3DSliceToCSIM($i,$xc,$yc,$height,$width,$thick,$sa,$ea) {  //Slice number, ellipse centre (x,y), height, width, start angle, end angle
    7882
    79         $sa *= M_PI/180;
    80         $ea *= M_PI/180;
    81 
    82         //add coordinates of the centre to the map
    83         $coords = "$xc, $yc";
    84 
    85         //add coordinates of the first point on the arc to the map
    86         $xp = floor($width*cos($sa)/2+$xc);
    87         $yp = floor($yc-$height*sin($sa)/2);
    88         $coords.= ", $xp, $yp";
    89 
    90         //If on the front half, add the thickness offset
    91         if ($sa >= M_PI && $sa <= 2*M_PI*1.01) {
    92             $yp = floor($yp+$thick);
    93             $coords.= ", $xp, $yp";
    94         }
    95 
    96         //add coordinates every 0.2 radians
    97         $a=$sa+0.2;
    98         while ($a<$ea) {
    99             $xp = floor($width*cos($a)/2+$xc);
    100             if ($a >= M_PI && $a <= 2*M_PI*1.01) {
    101                 $yp = floor($yc-($height*sin($a)/2)+$thick);
    102             } else {
    103                 $yp = floor($yc-$height*sin($a)/2);
    104             }
    105             $coords.= ", $xp, $yp";
    106             $a += 0.2;
    107         }
    108 
    109         //Add the last point on the arc
    110         $xp = floor($width*cos($ea)/2+$xc);
    111         $yp = floor($yc-$height*sin($ea)/2);
    112 
    113 
    114         if ($ea >= M_PI && $ea <= 2*M_PI*1.01) {
    115             $coords.= ", $xp, ".floor($yp+$thick);
    116         }
    117         $coords.= ", $xp, $yp";
    118         $alt='';
    119 
    120         if( !empty($this->csimtargets[$i]) ) {
    121             $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtargets[$i]."\"";
    122 
    123             if( !empty($this->csimwintargets[$i]) ) {
    124                 $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
    125             }
    126             
    127             if( !empty($this->csimalts[$i]) ) {
    128                 $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
    129                 $this->csimareas .= "alt=\"$tmp\" title=\"$tmp\" ";
    130             }
    131             $this->csimareas .=  " />\n";
    132         }
     83        $sa *= M_PI/180;
     84        $ea *= M_PI/180;
     85
     86        //add coordinates of the centre to the map
     87        $coords = "$xc, $yc";
     88
     89        //add coordinates of the first point on the arc to the map
     90        $xp = floor($width*cos($sa)/2+$xc);
     91        $yp = floor($yc-$height*sin($sa)/2);
     92        $coords.= ", $xp, $yp";
     93
     94        //If on the front half, add the thickness offset
     95        if ($sa >= M_PI && $sa <= 2*M_PI*1.01) {
     96            $yp = floor($yp+$thick);
     97            $coords.= ", $xp, $yp";
     98        }
     99               
     100        //add coordinates every 0.2 radians
     101        $a=$sa+0.2;
     102        while ($a<$ea) {
     103            $xp = floor($width*cos($a)/2+$xc);
     104            if ($a >= M_PI && $a <= 2*M_PI*1.01) {
     105                $yp = floor($yc-($height*sin($a)/2)+$thick);
     106            } else {
     107                $yp = floor($yc-$height*sin($a)/2);
     108            }
     109            $coords.= ", $xp, $yp";
     110            $a += 0.2;
     111        }
     112               
     113        //Add the last point on the arc
     114        $xp = floor($width*cos($ea)/2+$xc);
     115        $yp = floor($yc-$height*sin($ea)/2);
     116
     117
     118        if ($ea >= M_PI && $ea <= 2*M_PI*1.01) {
     119            $coords.= ", $xp, ".floor($yp+$thick);
     120        }
     121        $coords.= ", $xp, $yp";
     122        $alt='';
     123
     124        if( !empty($this->csimtargets[$i]) ) {
     125            $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".$this->csimtargets[$i]."\"";
     126       
     127            if( !empty($this->csimwintargets[$i]) ) {
     128                $this->csimareas .= " target=\"".$this->csimwintargets[$i]."\" ";
     129            }
     130           
     131            if( !empty($this->csimalts[$i]) ) {                                                                         
     132                $tmp=sprintf($this->csimalts[$i],$this->data[$i]);
     133                $this->csimareas .= "alt=\"$tmp\" title=\"$tmp\" ";
     134            }
     135            $this->csimareas .=  " />\n";
     136        }
    133137
    134138    }
    135139
    136140    function SetLabels($aLabels,$aLblPosAdj="auto") {
    137         $this->labels = $aLabels;
    138         $this->ilabelposadj=$aLblPosAdj;
    139     }
    140 
    141 
     141        $this->labels = $aLabels;
     142        $this->ilabelposadj=$aLblPosAdj;
     143    }
     144
     145       
    142146    // Distance from the pie to the labels
    143147    function SetLabelMargin($m) {
    144         $this->value->SetMargin($m);
    145     }
    146 
     148        $this->value->SetMargin($m);
     149    }
     150       
    147151    // Show a thin line from the pie to the label for a specific slice
    148152    function ShowLabelHint($f=true) {
    149         $this->showlabelhint=$f;
    150     }
    151 
     153        $this->showlabelhint=$f;
     154    }
     155       
    152156    // Set color of hint line to label for each slice
    153157    function SetLabelHintColor($c) {
    154         $this->labelhintcolor=$c;
     158        $this->labelhintcolor=$c;
    155159    }
    156160
    157161    function SetHeight($aHeight) {
    158         $this->iThickness = $aHeight;
    159     }
    160 
    161 
    162     // Normalize Angle between 0-360
     162      $this->iThickness = $aHeight;
     163    }
     164
     165
     166// Normalize Angle between 0-360
    163167    function NormAngle($a) {
    164         // Normalize anle to 0 to 2M_PI
    165         //
    166         if( $a > 0 ) {
    167             while($a > 360) $a -= 360;
    168         }
    169         else {
    170             while($a < 0) $a += 360;
    171         }
    172         if( $a < 0 )
    173         $a = 360 + $a;
    174 
    175         if( $a == 360 ) $a=0;
    176         return $a;
    177     }
    178 
    179 
    180 
    181     // Draw one 3D pie slice at position ($xc,$yc) with height $z
     168        // Normalize anle to 0 to 2M_PI
     169        //
     170        if( $a > 0 ) {
     171            while($a > 360) $a -= 360;
     172        }
     173        else {
     174            while($a < 0) $a += 360;
     175        }
     176        if( $a < 0 )
     177            $a = 360 + $a;
     178
     179        if( $a == 360 ) $a=0;
     180        return $a;
     181    }
     182
     183   
     184
     185// Draw one 3D pie slice at position ($xc,$yc) with height $z
    182186    function Pie3DSlice($img,$xc,$yc,$w,$h,$sa,$ea,$z,$fillcolor,$shadow=0.65) {
    183 
    184         // Due to the way the 3D Pie algorithm works we are
    185         // guaranteed that any slice we get into this method
    186         // belongs to either the left or right side of the
    187         // pie ellipse. Hence, no slice will cross 90 or 270
    188         // point.
    189         if( ($sa < 90 && $ea > 90) || ( ($sa > 90 && $sa < 270) && $ea > 270) ) {
    190             JpGraphError::RaiseL(14003);//('Internal assertion failed. Pie3D::Pie3DSlice');
    191             exit(1);
    192         }
    193 
    194         $p[] = array();
    195 
    196         // Setup pre-calculated values
    197         $rsa = $sa/180*M_PI; // to Rad
    198         $rea = $ea/180*M_PI; // to Rad
    199         $sinsa = sin($rsa);
    200         $cossa = cos($rsa);
    201         $sinea = sin($rea);
    202         $cosea = cos($rea);
    203 
    204         // p[] is the points for the overall slice and
    205         // pt[] is the points for the top pie
    206 
    207         // Angular step when approximating the arc with a polygon train.
    208         $step = 0.05;
    209 
    210         if( $sa >= 270 ) {
    211             if( $ea > 360 || ($ea > 0 && $ea <= 90) ) {
    212                 if( $ea > 0 && $ea <= 90 ) {
    213                     // Adjust angle to simplify conditions in loops
    214                     $rea += 2*M_PI;
    215                 }
    216 
    217                 $p = array($xc,$yc,$xc,$yc+$z,
    218                 $xc+$w*$cossa,$z+$yc-$h*$sinsa);
    219                 $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa);
    220 
    221                 for( $a=$rsa; $a < 2*M_PI; $a += $step ) {
    222                     $tca = cos($a);
    223                     $tsa = sin($a);
    224                     $p[] = $xc+$w*$tca;
    225                     $p[] = $z+$yc-$h*$tsa;
    226                     $pt[] = $xc+$w*$tca;
    227                     $pt[] = $yc-$h*$tsa;
    228                 }
    229 
    230                 $pt[] = $xc+$w;
    231                 $pt[] = $yc;
    232 
    233                 $p[] = $xc+$w;
    234                 $p[] = $z+$yc;
    235                 $p[] = $xc+$w;
    236                 $p[] = $yc;
    237                 $p[] = $xc;
    238                 $p[] = $yc;
    239 
    240                 for( $a=2*M_PI+$step; $a < $rea; $a += $step ) {
    241                     $pt[] = $xc + $w*cos($a);
    242                     $pt[] = $yc - $h*sin($a);
    243                 }
    244 
    245                 $pt[] = $xc+$w*$cosea;
    246                 $pt[] = $yc-$h*$sinea;
    247                 $pt[] = $xc;
    248                 $pt[] = $yc;
    249 
    250             }
    251             else {
    252                 $p = array($xc,$yc,$xc,$yc+$z,
    253                 $xc+$w*$cossa,$z+$yc-$h*$sinsa);
    254                 $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa);
    255 
    256                 $rea = $rea == 0.0 ? 2*M_PI : $rea;
    257                 for( $a=$rsa; $a < $rea; $a += $step ) {
    258                     $tca = cos($a);
    259                     $tsa = sin($a);
    260                     $p[] = $xc+$w*$tca;
    261                     $p[] = $z+$yc-$h*$tsa;
    262                     $pt[] = $xc+$w*$tca;
    263                     $pt[] = $yc-$h*$tsa;
    264                 }
    265 
    266                 $pt[] = $xc+$w*$cosea;
    267                 $pt[] = $yc-$h*$sinea;
    268                 $pt[] = $xc;
    269                 $pt[] = $yc;
    270 
    271                 $p[] = $xc+$w*$cosea;
    272                 $p[] = $z+$yc-$h*$sinea;
    273                 $p[] = $xc+$w*$cosea;
    274                 $p[] = $yc-$h*$sinea;
    275                 $p[] = $xc;
    276                 $p[] = $yc;
    277             }
    278         }
    279         elseif( $sa >= 180 ) {
    280             $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea);
    281             $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea);
    282 
    283             for( $a=$rea; $a>$rsa; $a -= $step ) {
    284                 $tca = cos($a);
    285                 $tsa = sin($a);
    286                 $p[] = $xc+$w*$tca;
    287                 $p[] = $z+$yc-$h*$tsa;
    288                 $pt[] = $xc+$w*$tca;
    289                 $pt[] = $yc-$h*$tsa;
    290             }
    291 
    292             $pt[] = $xc+$w*$cossa;
    293             $pt[] = $yc-$h*$sinsa;
    294             $pt[] = $xc;
    295             $pt[] = $yc;
    296 
    297             $p[] = $xc+$w*$cossa;
    298             $p[] = $z+$yc-$h*$sinsa;
    299             $p[] = $xc+$w*$cossa;
    300             $p[] = $yc-$h*$sinsa;
    301             $p[] = $xc;
    302             $p[] = $yc;
    303 
    304         }
    305         elseif( $sa >= 90 ) {
    306             if( $ea > 180 ) {
    307                 $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea);
    308                 $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea);
    309 
    310                 for( $a=$rea; $a > M_PI; $a -= $step ) {
    311                     $tca = cos($a);
    312                     $tsa = sin($a);
    313                     $p[] = $xc+$w*$tca;
    314                     $p[] = $z + $yc - $h*$tsa;
    315                     $pt[] = $xc+$w*$tca;
    316                     $pt[] = $yc-$h*$tsa;
    317                 }
    318 
    319                 $p[] = $xc-$w;
    320                 $p[] = $z+$yc;
    321                 $p[] = $xc-$w;
    322                 $p[] = $yc;
    323                 $p[] = $xc;
    324                 $p[] = $yc;
    325 
    326                 $pt[] = $xc-$w;
    327                 $pt[] = $z+$yc;
    328                 $pt[] = $xc-$w;
    329                 $pt[] = $yc;
    330 
    331                 for( $a=M_PI-$step; $a > $rsa; $a -= $step ) {
    332                     $pt[] = $xc + $w*cos($a);
    333                     $pt[] = $yc - $h*sin($a);
    334                 }
    335 
    336                 $pt[] = $xc+$w*$cossa;
    337                 $pt[] = $yc-$h*$sinsa;
    338                 $pt[] = $xc;
    339                 $pt[] = $yc;
    340 
    341             }
    342             else { // $sa >= 90 && $ea <= 180
    343                 $p = array($xc,$yc,$xc,$yc+$z,
    344                 $xc+$w*$cosea,$z+$yc-$h*$sinea,
    345                 $xc+$w*$cosea,$yc-$h*$sinea,
    346                 $xc,$yc);
    347 
    348                 $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea);
    349 
    350                 for( $a=$rea; $a>$rsa; $a -= $step ) {
    351                     $pt[] = $xc + $w*cos($a);
    352                     $pt[] = $yc - $h*sin($a);
    353                 }
    354 
    355                 $pt[] = $xc+$w*$cossa;
    356                 $pt[] = $yc-$h*$sinsa;
    357                 $pt[] = $xc;
    358                 $pt[] = $yc;
    359 
    360             }
    361         }
    362         else { // sa > 0 && ea < 90
    363 
    364             $p = array($xc,$yc,$xc,$yc+$z,
    365             $xc+$w*$cossa,$z+$yc-$h*$sinsa,
    366             $xc+$w*$cossa,$yc-$h*$sinsa,
    367             $xc,$yc);
    368 
    369             $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa);
    370 
    371             for( $a=$rsa; $a < $rea; $a += $step ) {
    372                 $pt[] = $xc + $w*cos($a);
    373                 $pt[] = $yc - $h*sin($a);
    374             }
    375 
    376             $pt[] = $xc+$w*$cosea;
    377             $pt[] = $yc-$h*$sinea;
    378             $pt[] = $xc;
    379             $pt[] = $yc;
    380         }
    381         
    382         $img->PushColor($fillcolor.":".$shadow);
    383         $img->FilledPolygon($p);
    384         $img->PopColor();
    385 
    386         $img->PushColor($fillcolor);
    387         $img->FilledPolygon($pt);
    388         $img->PopColor();
     187       
     188        // Due to the way the 3D Pie algorithm works we are
     189        // guaranteed that any slice we get into this method
     190        // belongs to either the left or right side of the
     191        // pie ellipse. Hence, no slice will cross 90 or 270
     192        // point.
     193        if( ($sa < 90 && $ea > 90) || ( ($sa > 90 && $sa < 270) && $ea > 270) ) {
     194            JpGraphError::RaiseL(14003);//('Internal assertion failed. Pie3D::Pie3DSlice');
     195            exit(1);
     196        }
     197
     198        $p[] = array();
     199
     200        // Setup pre-calculated values
     201        $rsa = $sa/180*M_PI;    // to Rad
     202        $rea = $ea/180*M_PI;    // to Rad
     203        $sinsa = sin($rsa);
     204        $cossa = cos($rsa);
     205        $sinea = sin($rea);
     206        $cosea = cos($rea);
     207
     208        // p[] is the points for the overall slice and
     209        // pt[] is the points for the top pie
     210
     211        // Angular step when approximating the arc with a polygon train.
     212        $step = 0.05;
     213
     214        if( $sa >= 270 ) {
     215            if( $ea > 360 || ($ea > 0 && $ea <= 90) ) {
     216                if( $ea > 0 && $ea <= 90 ) {
     217                    // Adjust angle to simplify conditions in loops
     218                    $rea += 2*M_PI;
     219                }
     220
     221                $p = array($xc,$yc,$xc,$yc+$z,
     222                           $xc+$w*$cossa,$z+$yc-$h*$sinsa);
     223                $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa);
     224
     225                for( $a=$rsa; $a < 2*M_PI; $a += $step ) {
     226                    $tca = cos($a);
     227                    $tsa = sin($a);
     228                    $p[] = $xc+$w*$tca;
     229                    $p[] = $z+$yc-$h*$tsa;
     230                    $pt[] = $xc+$w*$tca;
     231                    $pt[] = $yc-$h*$tsa;
     232                }
     233
     234                $pt[] = $xc+$w;
     235                $pt[] = $yc;
     236
     237                $p[] = $xc+$w;
     238                $p[] = $z+$yc;
     239                $p[] = $xc+$w;
     240                $p[] = $yc;
     241                $p[] = $xc;
     242                $p[] = $yc;
     243
     244                for( $a=2*M_PI+$step; $a < $rea; $a += $step ) {
     245                    $pt[] = $xc + $w*cos($a);
     246                    $pt[] = $yc - $h*sin($a);
     247                }
     248                   
     249                $pt[] = $xc+$w*$cosea;
     250                $pt[] = $yc-$h*$sinea;
     251                $pt[] = $xc;
     252                $pt[] = $yc;
     253
     254            }
     255            else {
     256                $p = array($xc,$yc,$xc,$yc+$z,
     257                           $xc+$w*$cossa,$z+$yc-$h*$sinsa);
     258                $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa);
     259                   
     260                $rea = $rea == 0.0 ? 2*M_PI : $rea;
     261                for( $a=$rsa; $a < $rea; $a += $step ) {
     262                    $tca = cos($a);
     263                    $tsa = sin($a);
     264                    $p[] = $xc+$w*$tca;
     265                    $p[] = $z+$yc-$h*$tsa;
     266                    $pt[] = $xc+$w*$tca;
     267                    $pt[] = $yc-$h*$tsa;
     268                }
     269
     270                $pt[] = $xc+$w*$cosea;
     271                $pt[] = $yc-$h*$sinea;
     272                $pt[] = $xc;
     273                $pt[] = $yc;
     274                   
     275                $p[] = $xc+$w*$cosea;
     276                $p[] = $z+$yc-$h*$sinea;
     277                $p[] = $xc+$w*$cosea;
     278                $p[] = $yc-$h*$sinea;
     279                $p[] = $xc;
     280                $p[] = $yc;
     281            }
     282        }
     283        elseif( $sa >= 180 ) {
     284            $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea);
     285            $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea);
     286               
     287            for( $a=$rea; $a>$rsa; $a -= $step ) {
     288                $tca = cos($a);
     289                $tsa = sin($a);
     290                $p[] = $xc+$w*$tca;
     291                $p[] = $z+$yc-$h*$tsa;
     292                $pt[] = $xc+$w*$tca;
     293                $pt[] = $yc-$h*$tsa;
     294            }
     295
     296            $pt[] = $xc+$w*$cossa;
     297            $pt[] = $yc-$h*$sinsa;
     298            $pt[] = $xc;
     299            $pt[] = $yc;
     300               
     301            $p[] = $xc+$w*$cossa;
     302            $p[] = $z+$yc-$h*$sinsa;
     303            $p[] = $xc+$w*$cossa;
     304            $p[] = $yc-$h*$sinsa;
     305            $p[] = $xc;
     306            $p[] = $yc;
     307       
     308        }
     309        elseif( $sa >= 90 ) {
     310            if( $ea > 180 ) {
     311                $p = array($xc,$yc,$xc,$yc+$z,$xc+$w*$cosea,$z+$yc-$h*$sinea);
     312                $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea);
     313
     314                for( $a=$rea; $a > M_PI; $a -= $step ) {
     315                    $tca = cos($a);
     316                    $tsa = sin($a);                 
     317                    $p[] = $xc+$w*$tca;
     318                    $p[] = $z + $yc - $h*$tsa;
     319                    $pt[] = $xc+$w*$tca;
     320                    $pt[] = $yc-$h*$tsa;
     321                }
     322
     323                $p[] = $xc-$w;
     324                $p[] = $z+$yc;
     325                $p[] = $xc-$w;
     326                $p[] = $yc;
     327                $p[] = $xc;
     328                $p[] = $yc;
     329
     330                $pt[] = $xc-$w;
     331                $pt[] = $z+$yc;
     332                $pt[] = $xc-$w;
     333                $pt[] = $yc;
     334
     335                for( $a=M_PI-$step; $a > $rsa; $a -= $step ) {
     336                    $pt[] = $xc + $w*cos($a);
     337                    $pt[] = $yc - $h*sin($a);
     338                }
     339
     340                $pt[] = $xc+$w*$cossa;
     341                $pt[] = $yc-$h*$sinsa;
     342                $pt[] = $xc;
     343                $pt[] = $yc;
     344
     345            }
     346            else { // $sa >= 90 && $ea <= 180
     347                $p = array($xc,$yc,$xc,$yc+$z,
     348                           $xc+$w*$cosea,$z+$yc-$h*$sinea,
     349                           $xc+$w*$cosea,$yc-$h*$sinea,
     350                           $xc,$yc);
     351
     352                $pt = array($xc,$yc,$xc+$w*$cosea,$yc-$h*$sinea);
     353
     354                for( $a=$rea; $a>$rsa; $a -= $step ) {
     355                    $pt[] = $xc + $w*cos($a);
     356                    $pt[] = $yc - $h*sin($a);
     357                }
     358
     359                $pt[] = $xc+$w*$cossa;
     360                $pt[] = $yc-$h*$sinsa;
     361                $pt[] = $xc;
     362                $pt[] = $yc;
     363
     364            }
     365        }
     366        else { // sa > 0 && ea < 90
     367
     368            $p = array($xc,$yc,$xc,$yc+$z,
     369                       $xc+$w*$cossa,$z+$yc-$h*$sinsa,
     370                       $xc+$w*$cossa,$yc-$h*$sinsa,
     371                       $xc,$yc);
     372
     373            $pt = array($xc,$yc,$xc+$w*$cossa,$yc-$h*$sinsa);
     374
     375            for( $a=$rsa; $a < $rea; $a += $step ) {
     376                $pt[] = $xc + $w*cos($a);
     377                $pt[] = $yc - $h*sin($a);
     378            }
     379
     380            $pt[] = $xc+$w*$cosea;
     381            $pt[] = $yc-$h*$sinea;
     382            $pt[] = $xc;
     383            $pt[] = $yc;
     384        }
     385           
     386        $img->PushColor($fillcolor.":".$shadow);
     387        $img->FilledPolygon($p);
     388        $img->PopColor();
     389
     390        $img->PushColor($fillcolor);
     391        $img->FilledPolygon($pt);
     392        $img->PopColor();
    389393    }
    390394
    391395    function SetStartAngle($aStart) {
    392         if( $aStart < 0 || $aStart > 360 ) {
    393             JpGraphError::RaiseL(14004);//('Slice start angle must be between 0 and 360 degrees.');
    394         }
    395         $this->startangle = $aStart;
    396     }
    397 
    398     // Draw a 3D Pie
     396        if( $aStart < 0 || $aStart > 360 ) {
     397            JpGraphError::RaiseL(14004);//('Slice start angle must be between 0 and 360 degrees.');
     398        }
     399        $this->startangle = $aStart;
     400    }
     401   
     402// Draw a 3D Pie
    399403    function Pie3D($aaoption,$img,$data,$colors,$xc,$yc,$d,$angle,$z,
    400                    $shadow=0.65,$startangle=0,$edgecolor="",$edgeweight=1) {
    401 
    402         //---------------------------------------------------------------------------
    403         // As usual the algorithm get more complicated than I originally
    404         // envisioned. I believe that this is as simple as it is possible
    405         // to do it with the features I want. It's a good exercise to start
    406         // thinking on how to do this to convince your self that all this
    407         // is really needed for the general case.
    408         //
    409         // The algorithm two draw 3D pies without "real 3D" is done in
    410         // two steps.
    411         // First imagine the pie cut in half through a thought line between
    412         // 12'a clock and 6'a clock. It now easy to imagine that we can plot
    413         // the individual slices for each half by starting with the topmost
    414         // pie slice and continue down to 6'a clock.
    415         //
    416         // In the algortithm this is done in three principal steps
    417         // Step 1. Do the knife cut to ensure by splitting slices that extends
    418         // over the cut line. This is done by splitting the original slices into
    419         // upto 3 subslices.
    420         // Step 2. Find the top slice for each half
    421         // Step 3. Draw the slices from top to bottom
    422         //
    423         // The thing that slightly complicates this scheme with all the
    424         // angle comparisons below is that we can have an arbitrary start
    425         // angle so we must take into account the different equivalence classes.
    426         // For the same reason we must walk through the angle array in a
    427         // modulo fashion.
    428         //
    429         // Limitations of algorithm:
    430         // * A small exploded slice which crosses the 270 degree point
    431         //   will get slightly nagged close to the center due to the fact that
    432         //   we print the slices in Z-order and that the slice left part
    433         //   get printed first and might get slightly nagged by a larger
    434         //   slice on the right side just before the right part of the small
    435         //   slice. Not a major problem though.
    436         //---------------------------------------------------------------------------
    437 
    438 
    439         // Determine the height of the ellippse which gives an
    440         // indication of the inclination angle
    441         $h = ($angle/90.0)*$d;
    442         $sum = 0;
    443         for($i=0; $i<count($data); ++$i ) {
    444             $sum += $data[$i];
    445         }
    446 
    447         // Special optimization
    448         if( $sum==0 ) return;
    449 
    450         if( $this->labeltype == 2 ) {
    451             $this->adjusted_data = $this->AdjPercentage($data);
    452         }
    453 
    454         // Setup the start
    455         $accsum = 0;
    456         $a = $startangle;
    457         $a = $this->NormAngle($a);
    458 
    459         //
    460         // Step 1 . Split all slices that crosses 90 or 270
    461         //
    462         $idx=0;
    463         $adjexplode=array();
    464         $numcolors = count($colors);
    465         for($i=0; $i<count($data); ++$i, ++$idx ) {
    466             $da = $data[$i]/$sum * 360;
    467 
    468             if( empty($this->explode_radius[$i]) ) {
    469                 $this->explode_radius[$i]=0;
    470             }
    471 
    472             $expscale=1;
    473             if( $aaoption == 1 ) {
    474                 $expscale=2;
    475             }
    476 
    477             $la = $a + $da/2;
    478             $explode = array( $xc + $this->explode_radius[$i]*cos($la*M_PI/180)*$expscale,
    479             $yc - $this->explode_radius[$i]*sin($la*M_PI/180) * ($h/$d) *$expscale );
    480             $adjexplode[$idx] = $explode;
    481             $labeldata[$i] = array($la,$explode[0],$explode[1]);
    482             $originalangles[$i] = array($a,$a+$da);
    483 
    484             $ne = $this->NormAngle($a+$da);
    485             if( $da <= 180 ) {
    486                 // If the slice size is <= 90 it can at maximum cut across
    487                 // one boundary (either 90 or 270) where it needs to be split
    488                 $split=-1; // no split
    489                 if( ($da<=90 && ($a <= 90 && $ne > 90)) ||
    490                 (($da <= 180 && $da >90)  && (($a < 90 || $a >= 270) && $ne > 90)) ) {
    491                     $split = 90;
    492                 }
    493                 elseif( ($da<=90 && ($a <= 270 && $ne > 270)) ||
    494                 (($da<=180 && $da>90) && ($a >= 90 && $a < 270 && ($a+$da) > 270 )) ) {
    495                     $split = 270;
    496                 }
    497                 if( $split > 0 ) { // split in two
    498                     $angles[$idx] = array($a,$split);
    499                     $adjcolors[$idx] = $colors[$i % $numcolors];
    500                     $adjexplode[$idx] = $explode;
    501                     $angles[++$idx] = array($split,$ne);
    502                     $adjcolors[$idx] = $colors[$i % $numcolors];
    503                     $adjexplode[$idx] = $explode;
    504                 }
    505                 else { // no split
    506                     $angles[$idx] = array($a,$ne);
    507                     $adjcolors[$idx] = $colors[$i  % $numcolors];
    508                     $adjexplode[$idx] = $explode;
    509                 }
    510             }
    511             else {
    512                 // da>180
    513                 // Slice may, depending on position, cross one or two
    514                 // bonudaries
    515 
    516                 if( $a < 90 )        $split = 90;
    517                 elseif( $a <= 270 )  $split = 270;
    518                 else                 $split = 90;
    519 
    520                 $angles[$idx] = array($a,$split);
    521                 $adjcolors[$idx] = $colors[$i % $numcolors];
    522                 $adjexplode[$idx] = $explode;
    523                 //if( $a+$da > 360-$split ) {
    524                 // For slices larger than 270 degrees we might cross
    525                 // another boundary as well. This means that we must
    526                 // split the slice further. The comparison gets a little
    527                 // bit complicated since we must take into accound that
    528                 // a pie might have a startangle >0 and hence a slice might
    529                 // wrap around the 0 angle.
    530                 // Three cases:
    531                 //  a) Slice starts before 90 and hence gets a split=90, but
    532                 //     we must also check if we need to split at 270
    533                 //  b) Slice starts after 90 but before 270 and slices
    534                 //     crosses 90 (after a wrap around of 0)
    535                 //  c) If start is > 270 (hence the firstr split is at 90)
    536                 //     and the slice is so large that it goes all the way
    537                 //     around 270.
    538                 if( ($a < 90 && ($a+$da > 270)) || ($a > 90 && $a<=270 && ($a+$da>360+90) ) || ($a > 270 && $this->NormAngle($a+$da)>270) ) {
    539                     $angles[++$idx] = array($split,360-$split);
    540                     $adjcolors[$idx] = $colors[$i % $numcolors];
    541                     $adjexplode[$idx] = $explode;
    542                     $angles[++$idx] = array(360-$split,$ne);
    543                     $adjcolors[$idx] = $colors[$i % $numcolors];
    544                     $adjexplode[$idx] = $explode;
    545                 }
    546                 else {
    547                     // Just a simple split to the previous decided
    548                     // angle.
    549                     $angles[++$idx] = array($split,$ne);
    550                     $adjcolors[$idx] = $colors[$i % $numcolors];
    551                     $adjexplode[$idx] = $explode;
    552                 }
    553             }
    554             $a += $da;
    555             $a = $this->NormAngle($a);
    556         }
    557 
    558         // Total number of slices
    559         $n = count($angles);
    560 
    561         for($i=0; $i<$n; ++$i) {
    562             list($dbgs,$dbge) = $angles[$i];
    563         }
    564 
    565         //
    566         // Step 2. Find start index (first pie that starts in upper left quadrant)
    567         //
    568         $minval = $angles[0][0];
    569         $min = 0;
    570         for( $i=0; $i<$n; ++$i ) {
    571             if( $angles[$i][0] < $minval ) {
    572                 $minval = $angles[$i][0];
    573                 $min = $i;
    574             }
    575         }
    576         $j = $min;
    577         $cnt = 0;
    578         while( $angles[$j][1] <= 90 ) {
    579             $j++;
    580             if( $j>=$n) {
    581                 $j=0;
    582             }
    583             if( $cnt > $n ) {
    584                 JpGraphError::RaiseL(14005);
    585                 //("Pie3D Internal error (#1). Trying to wrap twice when looking for start index");
    586             }
    587             ++$cnt;
    588         }
    589         $start = $j;
    590 
    591         //
    592         // Step 3. Print slices in z-order
    593         //
    594         $cnt = 0;
    595 
    596         // First stroke all the slices between 90 and 270 (left half circle)
    597         // counterclockwise
    598          
    599         while( $angles[$j][0] < 270  && $aaoption !== 2 ) {
    600 
    601             list($x,$y) = $adjexplode[$j];
    602 
    603             $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1],
    604             $z,$adjcolors[$j],$shadow);
    605 
    606             $last = array($x,$y,$j);
    607 
    608             $j++;
    609             if( $j >= $n ) $j=0;
    610             if( $cnt > $n ) {
    611                 JpGraphError::RaiseL(14006);
    612                 //("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking.");
    613             }
    614             ++$cnt;
    615         }
    616          
    617         $slice_left = $n-$cnt;
    618         $j=$start-1;
    619         if($j<0) $j=$n-1;
    620         $cnt = 0;
    621 
    622         // The stroke all slices from 90 to -90 (right half circle)
    623         // clockwise
    624         while( $cnt < $slice_left  && $aaoption !== 2 ) {
    625 
    626             list($x,$y) = $adjexplode[$j];
    627 
    628             $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1],
    629             $z,$adjcolors[$j],$shadow);
    630             $j--;
    631             if( $cnt > $n ) {
    632                 JpGraphError::RaiseL(14006);
    633                 //("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking.");
    634             }
    635             if($j<0) $j=$n-1;
    636             $cnt++;
    637         }
    638 
    639         // Now do a special thing. Stroke the last slice on the left
    640         // halfcircle one more time.  This is needed in the case where
    641         // the slice close to 270 have been exploded. In that case the
    642         // part of the slice close to the center of the pie might be
    643         // slightly nagged.
    644         if( $aaoption !== 2 )
    645         $this->Pie3DSlice($img,$last[0],$last[1],$d,$h,$angles[$last[2]][0],
    646         $angles[$last[2]][1],$z,$adjcolors[$last[2]],$shadow);
    647 
    648 
    649         if( $aaoption !== 1 ) {
    650             // Now print possible labels and add csim
    651             $this->value->ApplyFont($img);
    652             $margin = $img->GetFontHeight()/2 + $this->value->margin ;
    653             for($i=0; $i < count($data); ++$i ) {
    654                 $la = $labeldata[$i][0];
    655                 $x = $labeldata[$i][1] + cos($la*M_PI/180)*($d+$margin)*$this->ilabelposadj;
    656                 $y = $labeldata[$i][2] - sin($la*M_PI/180)*($h+$margin)*$this->ilabelposadj;
    657                 if( $this->ilabelposadj >= 1.0 ) {
    658                     if( $la > 180 && $la < 360 ) $y += $z;
    659                 }
    660                 if( $this->labeltype == 0 ) {
    661                     if( $sum > 0 ) $l = 100*$data[$i]/$sum;
    662                     else $l = 0;
    663                 }
    664                 elseif( $this->labeltype == 1 ) {
    665                     $l = $data[$i];
    666                 }
    667                 else {
    668                     $l = $this->adjusted_data[$i];
    669                 }
    670                 if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) {
    671                     $l=sprintf($this->labels[$i],$l);
    672                 }
    673 
    674                 $this->StrokeLabels($l,$img,$labeldata[$i][0]*M_PI/180,$x,$y,$z);
    675                  
    676                 $this->Add3DSliceToCSIM($i,$labeldata[$i][1],$labeldata[$i][2],$h*2,$d*2,$z,
    677                 $originalangles[$i][0],$originalangles[$i][1]);
    678             }
    679         }
    680 
    681         //
    682         // Finally add potential lines in pie
    683         //
    684 
    685         if( $edgecolor=="" || $aaoption !== 0 ) return;
    686 
    687         $accsum = 0;
    688         $a = $startangle;
    689         $a = $this->NormAngle($a);
    690 
    691         $a *= M_PI/180.0;
    692 
    693         $idx=0;
    694         $img->PushColor($edgecolor);
    695         $img->SetLineWeight($edgeweight);
    696 
    697         $fulledge = true;
    698         for($i=0; $i < count($data) && $fulledge; ++$i ) {
    699             if( empty($this->explode_radius[$i]) ) {
    700                 $this->explode_radius[$i]=0;
    701             }
    702             if( $this->explode_radius[$i] > 0 ) {
    703                 $fulledge = false;
    704             }
    705         }
    706          
    707 
    708         for($i=0; $i < count($data); ++$i, ++$idx ) {
    709 
    710             $da = $data[$i]/$sum * 2*M_PI;
    711             $this->StrokeFullSliceFrame($img,$xc,$yc,$a,$a+$da,$d,$h,$z,$edgecolor,
    712             $this->explode_radius[$i],$fulledge);
    713             $a += $da;
    714         }
    715         $img->PopColor();
     404                   $shadow=0.65,$startangle=0,$edgecolor="",$edgeweight=1) {
     405
     406        //---------------------------------------------------------------------------
     407        // As usual the algorithm get more complicated than I originally
     408        // envisioned. I believe that this is as simple as it is possible
     409        // to do it with the features I want. It's a good exercise to start
     410        // thinking on how to do this to convince your self that all this
     411        // is really needed for the general case.
     412        //
     413        // The algorithm two draw 3D pies without "real 3D" is done in
     414        // two steps.
     415        // First imagine the pie cut in half through a thought line between
     416        // 12'a clock and 6'a clock. It now easy to imagine that we can plot
     417        // the individual slices for each half by starting with the topmost
     418        // pie slice and continue down to 6'a clock.
     419        //
     420        // In the algortithm this is done in three principal steps
     421        // Step 1. Do the knife cut to ensure by splitting slices that extends
     422        // over the cut line. This is done by splitting the original slices into
     423        // upto 3 subslices.
     424        // Step 2. Find the top slice for each half
     425        // Step 3. Draw the slices from top to bottom
     426        //
     427        // The thing that slightly complicates this scheme with all the
     428        // angle comparisons below is that we can have an arbitrary start
     429        // angle so we must take into account the different equivalence classes.
     430        // For the same reason we must walk through the angle array in a
     431        // modulo fashion.
     432        //
     433        // Limitations of algorithm:
     434        // * A small exploded slice which crosses the 270 degree point
     435        //   will get slightly nagged close to the center due to the fact that
     436        //   we print the slices in Z-order and that the slice left part
     437        //   get printed first and might get slightly nagged by a larger
     438        //   slice on the right side just before the right part of the small
     439        //   slice. Not a major problem though.
     440        //---------------------------------------------------------------------------
     441
     442   
     443        // Determine the height of the ellippse which gives an
     444        // indication of the inclination angle
     445        $h = ($angle/90.0)*$d;
     446        $sum = 0;
     447        for($i=0; $i<count($data); ++$i ) {
     448            $sum += $data[$i];
     449        }
     450       
     451        // Special optimization
     452        if( $sum==0 ) return;
     453
     454        if( $this->labeltype == 2 ) {
     455            $this->adjusted_data = $this->AdjPercentage($data);
     456        }
     457
     458        // Setup the start
     459        $accsum = 0;
     460        $a = $startangle;
     461        $a = $this->NormAngle($a);
     462
     463        //
     464        // Step 1 . Split all slices that crosses 90 or 270
     465        //
     466        $idx=0;
     467        $adjexplode=array();
     468        $numcolors = count($colors);
     469        for($i=0; $i<count($data); ++$i, ++$idx ) {
     470            $da = $data[$i]/$sum * 360;
     471
     472            if( empty($this->explode_radius[$i]) )
     473                $this->explode_radius[$i]=0;
     474
     475            $expscale=1;
     476            if( $aaoption == 1 )
     477                $expscale=2;
     478
     479            $la = $a + $da/2;
     480            $explode = array( $xc + $this->explode_radius[$i]*cos($la*M_PI/180)*$expscale,
     481                              $yc - $this->explode_radius[$i]*sin($la*M_PI/180) * ($h/$d) *$expscale );
     482            $adjexplode[$idx] = $explode;
     483            $labeldata[$i] = array($la,$explode[0],$explode[1]);
     484            $originalangles[$i] = array($a,$a+$da);
     485
     486            $ne = $this->NormAngle($a+$da);
     487            if( $da <= 180 ) {
     488                // If the slice size is <= 90 it can at maximum cut across
     489                // one boundary (either 90 or 270) where it needs to be split
     490                $split=-1; // no split
     491                if( ($da<=90 && ($a <= 90 && $ne > 90)) ||
     492                    (($da <= 180 && $da >90)  && (($a < 90 || $a >= 270) && $ne > 90)) ) {
     493                    $split = 90;
     494                }
     495                elseif( ($da<=90 && ($a <= 270 && $ne > 270)) ||
     496                        (($da<=180 && $da>90) && ($a >= 90 && $a < 270 && ($a+$da) > 270 )) ) {
     497                    $split = 270;
     498                }
     499                if( $split > 0 ) { // split in two
     500                    $angles[$idx] = array($a,$split);
     501                    $adjcolors[$idx] = $colors[$i % $numcolors];
     502                    $adjexplode[$idx] = $explode;
     503                    $angles[++$idx] = array($split,$ne);
     504                    $adjcolors[$idx] = $colors[$i % $numcolors];
     505                    $adjexplode[$idx] = $explode;
     506                }
     507                else { // no split
     508                    $angles[$idx] = array($a,$ne);
     509                    $adjcolors[$idx] = $colors[$i  % $numcolors];
     510                    $adjexplode[$idx] = $explode;       
     511                }
     512            }
     513            else {
     514                // da>180
     515                // Slice may, depending on position, cross one or two
     516                // bonudaries
     517
     518                if( $a < 90 )
     519                    $split = 90;
     520                elseif( $a <= 270 )
     521                    $split = 270;
     522                else
     523                    $split = 90;
     524
     525                $angles[$idx] = array($a,$split);
     526                $adjcolors[$idx] = $colors[$i % $numcolors];
     527                $adjexplode[$idx] = $explode;
     528                //if( $a+$da > 360-$split ) {
     529                // For slices larger than 270 degrees we might cross
     530                // another boundary as well. This means that we must
     531                // split the slice further. The comparison gets a little
     532                // bit complicated since we must take into accound that
     533                // a pie might have a startangle >0 and hence a slice might
     534                // wrap around the 0 angle.
     535                // Three cases:
     536                //  a) Slice starts before 90 and hence gets a split=90, but
     537                //     we must also check if we need to split at 270
     538                //  b) Slice starts after 90 but before 270 and slices
     539                //     crosses 90 (after a wrap around of 0)
     540                //  c) If start is > 270 (hence the firstr split is at 90)
     541                //     and the slice is so large that it goes all the way
     542                //     around 270.
     543                if( ($a < 90 && ($a+$da > 270)) ||
     544                    ($a > 90 && $a<=270 && ($a+$da>360+90) ) ||
     545                    ($a > 270 && $this->NormAngle($a+$da)>270) ) {
     546                    $angles[++$idx] = array($split,360-$split);
     547                    $adjcolors[$idx] = $colors[$i % $numcolors];
     548                    $adjexplode[$idx] = $explode;
     549                    $angles[++$idx] = array(360-$split,$ne);
     550                    $adjcolors[$idx] = $colors[$i % $numcolors];
     551                    $adjexplode[$idx] = $explode;
     552                }       
     553                else {
     554                    // Just a simple split to the previous decided
     555                    // angle.
     556                    $angles[++$idx] = array($split,$ne);
     557                    $adjcolors[$idx] = $colors[$i % $numcolors];
     558                    $adjexplode[$idx] = $explode;
     559                }
     560            }
     561            $a += $da;
     562            $a = $this->NormAngle($a);
     563        }
     564
     565        // Total number of slices
     566        $n = count($angles);
     567
     568        for($i=0; $i<$n; ++$i) {
     569            list($dbgs,$dbge) = $angles[$i];
     570        }
     571
     572        //
     573        // Step 2. Find start index (first pie that starts in upper left quadrant)
     574        //
     575        $minval = $angles[0][0];
     576        $min = 0;
     577        for( $i=0; $i<$n; ++$i ) {
     578            if( $angles[$i][0] < $minval ) {
     579                $minval = $angles[$i][0];
     580                $min = $i;
     581            }
     582        }
     583        $j = $min;
     584        $cnt = 0;
     585        while( $angles[$j][1] <= 90 ) {
     586            $j++;
     587            if( $j>=$n) {
     588                $j=0;
     589            }
     590            if( $cnt > $n ) {
     591                JpGraphError::RaiseL(14005);
     592//("Pie3D Internal error (#1). Trying to wrap twice when looking for start index");
     593            }
     594            ++$cnt;
     595        }
     596        $start = $j;
     597
     598        //
     599        // Step 3. Print slices in z-order
     600        //
     601        $cnt = 0;
     602       
     603        // First stroke all the slices between 90 and 270 (left half circle)
     604        // counterclockwise
     605           
     606        while( $angles[$j][0] < 270  && $aaoption !== 2 ) {
     607
     608            list($x,$y) = $adjexplode[$j];
     609
     610            $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1],
     611                              $z,$adjcolors[$j],$shadow);
     612       
     613            $last = array($x,$y,$j);
     614
     615            $j++;
     616            if( $j >= $n ) $j=0;
     617            if( $cnt > $n ) {
     618                JpGraphError::RaiseL(14006);
     619//("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking.");
     620            }
     621            ++$cnt;
     622        }
     623     
     624        $slice_left = $n-$cnt;
     625        $j=$start-1;
     626        if($j<0) $j=$n-1;
     627        $cnt = 0;
     628       
     629        // The stroke all slices from 90 to -90 (right half circle)
     630        // clockwise
     631        while( $cnt < $slice_left  && $aaoption !== 2 ) {
     632
     633            list($x,$y) = $adjexplode[$j];
     634
     635            $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1],
     636                              $z,$adjcolors[$j],$shadow);
     637            $j--;
     638            if( $cnt > $n ) {
     639                JpGraphError::RaiseL(14006);
     640//("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking.");
     641            }
     642            if($j<0) $j=$n-1;
     643            $cnt++;
     644        }
     645       
     646        // Now do a special thing. Stroke the last slice on the left
     647        // halfcircle one more time.  This is needed in the case where
     648        // the slice close to 270 have been exploded. In that case the
     649        // part of the slice close to the center of the pie might be
     650        // slightly nagged.
     651        if( $aaoption !== 2 )
     652            $this->Pie3DSlice($img,$last[0],$last[1],$d,$h,$angles[$last[2]][0],
     653                              $angles[$last[2]][1],$z,$adjcolors[$last[2]],$shadow);
     654
     655
     656        if( $aaoption !== 1 ) {
     657            // Now print possible labels and add csim
     658            $this->value->ApplyFont($img);
     659            $margin = $img->GetFontHeight()/2 + $this->value->margin ;
     660            for($i=0; $i < count($data); ++$i ) {
     661                $la = $labeldata[$i][0];
     662                $x = $labeldata[$i][1] + cos($la*M_PI/180)*($d+$margin)*$this->ilabelposadj;
     663                $y = $labeldata[$i][2] - sin($la*M_PI/180)*($h+$margin)*$this->ilabelposadj;
     664                if( $this->ilabelposadj >= 1.0 ) {
     665                    if( $la > 180 && $la < 360 ) $y += $z;
     666                }
     667                if( $this->labeltype == 0 ) {
     668                    if( $sum > 0 )
     669                        $l = 100*$data[$i]/$sum;
     670                    else
     671                        $l = 0;
     672                }
     673                elseif( $this->labeltype == 1 ) {
     674                    $l = $data[$i];
     675                }
     676                else {
     677                    $l = $this->adjusted_data[$i];
     678                }
     679                if( isset($this->labels[$i]) && is_string($this->labels[$i]) )
     680                    $l=sprintf($this->labels[$i],$l);
     681
     682                $this->StrokeLabels($l,$img,$labeldata[$i][0]*M_PI/180,$x,$y,$z);
     683           
     684                $this->Add3DSliceToCSIM($i,$labeldata[$i][1],$labeldata[$i][2],$h*2,$d*2,$z,
     685                                      $originalangles[$i][0],$originalangles[$i][1]);
     686            }   
     687        }
     688
     689        //
     690        // Finally add potential lines in pie
     691        //
     692
     693        if( $edgecolor=="" || $aaoption !== 0 ) return;
     694
     695        $accsum = 0;
     696        $a = $startangle;
     697        $a = $this->NormAngle($a);
     698
     699        $a *= M_PI/180.0;
     700
     701        $idx=0;
     702        $img->PushColor($edgecolor);
     703        $img->SetLineWeight($edgeweight);
     704       
     705        $fulledge = true;
     706        for($i=0; $i < count($data) && $fulledge; ++$i ) {
     707            if( empty($this->explode_radius[$i]) )
     708                $this->explode_radius[$i]=0;
     709            if( $this->explode_radius[$i] > 0 ) {
     710                $fulledge = false;
     711            }
     712        }
     713           
     714
     715        for($i=0; $i < count($data); ++$i, ++$idx ) {
     716
     717            $da = $data[$i]/$sum * 2*M_PI;
     718            $this->StrokeFullSliceFrame($img,$xc,$yc,$a,$a+$da,$d,$h,$z,$edgecolor,
     719                                        $this->explode_radius[$i],$fulledge);
     720            $a += $da;
     721        }
     722        $img->PopColor();
    716723    }
    717724
    718725    function StrokeFullSliceFrame($img,$xc,$yc,$sa,$ea,$w,$h,$z,$edgecolor,$exploderadius,$fulledge) {
    719         $step = 0.02;
    720 
    721         if( $exploderadius > 0 ) {
    722             $la = ($sa+$ea)/2;
    723             $xc += $exploderadius*cos($la);
    724             $yc -= $exploderadius*sin($la) * ($h/$w) ;
    725              
    726         }
    727 
    728         $p = array($xc,$yc,$xc+$w*cos($sa),$yc-$h*sin($sa));
    729 
    730         for($a=$sa; $a < $ea; $a += $step ) {
    731             $p[] = $xc + $w*cos($a);
    732             $p[] = $yc - $h*sin($a);
    733         }
    734 
    735         $p[] = $xc+$w*cos($ea);
    736         $p[] = $yc-$h*sin($ea);
    737         $p[] = $xc;
    738         $p[] = $yc;
    739 
    740         $img->SetColor($edgecolor);
    741         $img->Polygon($p);
    742 
    743         // Unfortunately we can't really draw the full edge around the whole of
    744         // of the slice if any of the slices are exploded. The reason is that
    745         // this algorithm is to simply. There are cases where the edges will
    746         // "overwrite" other slices when they have been exploded.
    747         // Doing the full, proper 3D hidden lines stiff is actually quite
    748         // tricky. So for exploded pies we only draw the top edge. Not perfect
    749         // but the "real" solution is much more complicated.
    750         if( $fulledge && !( $sa > 0 && $sa < M_PI && $ea < M_PI) ) {
    751 
    752             if($sa < M_PI && $ea > M_PI) {
    753                 $sa = M_PI;
    754             }
    755 
    756             if($sa < 2*M_PI && (($ea >= 2*M_PI) || ($ea > 0 && $ea < $sa ) ) ) {
    757                 $ea = 2*M_PI;
    758             }
    759 
    760             if( $sa >= M_PI && $ea <= 2*M_PI ) {
    761                 $p = array($xc + $w*cos($sa),$yc - $h*sin($sa),
    762                 $xc + $w*cos($sa),$z + $yc - $h*sin($sa));
    763 
    764                 for($a=$sa+$step; $a < $ea; $a += $step ) {
    765                     $p[] = $xc + $w*cos($a);
    766                     $p[] = $z + $yc - $h*sin($a);
    767                 }
    768                 $p[] = $xc + $w*cos($ea);
    769                 $p[] = $z + $yc - $h*sin($ea);
    770                 $p[] = $xc + $w*cos($ea);
    771                 $p[] = $yc - $h*sin($ea);
    772                 $img->SetColor($edgecolor);
    773                 $img->Polygon($p);
    774             }
    775         }
     726        $step = 0.02;
     727
     728        if( $exploderadius > 0 ) {
     729            $la = ($sa+$ea)/2;
     730            $xc += $exploderadius*cos($la);
     731            $yc -= $exploderadius*sin($la) * ($h/$w) ;
     732           
     733        }
     734
     735        $p = array($xc,$yc,$xc+$w*cos($sa),$yc-$h*sin($sa));
     736
     737        for($a=$sa; $a < $ea; $a += $step ) {
     738            $p[] = $xc + $w*cos($a);
     739            $p[] = $yc - $h*sin($a);
     740        }
     741
     742        $p[] = $xc+$w*cos($ea);
     743        $p[] = $yc-$h*sin($ea);
     744        $p[] = $xc;
     745        $p[] = $yc;
     746
     747        $img->SetColor($edgecolor);
     748        $img->Polygon($p);
     749
     750        // Unfortunately we can't really draw the full edge around the whole of
     751        // of the slice if any of the slices are exploded. The reason is that
     752        // this algorithm is to simply. There are cases where the edges will
     753        // "overwrite" other slices when they have been exploded.
     754        // Doing the full, proper 3D hidden lines stiff is actually quite
     755        // tricky. So for exploded pies we only draw the top edge. Not perfect
     756        // but the "real" solution is much more complicated.
     757        if( $fulledge && !( $sa > 0 && $sa < M_PI && $ea < M_PI) ) {
     758
     759            if($sa < M_PI && $ea > M_PI)
     760                $sa = M_PI;
     761 
     762            if($sa < 2*M_PI && (($ea >= 2*M_PI) || ($ea > 0 && $ea < $sa ) ) )
     763                $ea = 2*M_PI;
     764
     765            if( $sa >= M_PI && $ea <= 2*M_PI ) {
     766                $p = array($xc + $w*cos($sa),$yc - $h*sin($sa),
     767                           $xc + $w*cos($sa),$z + $yc - $h*sin($sa));
     768               
     769                for($a=$sa+$step; $a < $ea; $a += $step ) {
     770                    $p[] = $xc + $w*cos($a);
     771                    $p[] = $z + $yc - $h*sin($a);
     772                }
     773                $p[] = $xc + $w*cos($ea);
     774                $p[] = $z + $yc - $h*sin($ea);
     775                $p[] = $xc + $w*cos($ea);
     776                $p[] = $yc - $h*sin($ea);
     777                $img->SetColor($edgecolor);
     778                $img->Polygon($p);         
     779            }
     780        }
    776781    }
    777782
    778783    function Stroke($img,$aaoption=0) {
    779         $n = count($this->data);
    780 
    781         // If user hasn't set the colors use the theme array
    782         if( $this->setslicecolors==null ) {
    783             $colors = array_keys($img->rgb->rgb_table);
    784             sort($colors);
    785             $idx_a=$this->themearr[$this->theme];
    786             $ca = array();
    787             $m = count($idx_a);
    788             for($i=0; $i < $m; ++$i) {
    789                 $ca[$i] = $colors[$idx_a[$i]];
    790             }
    791             $ca = array_reverse(array_slice($ca,0,$n));
    792         }
    793         else {
    794             $ca = $this->setslicecolors;
    795         }
    796 
    797 
    798         if( $this->posx <= 1 && $this->posx > 0 ) {
    799             $xc = round($this->posx*$img->width);
    800         }
    801         else {
    802             $xc = $this->posx ;
    803         }
    804 
    805         if( $this->posy <= 1 && $this->posy > 0 ) {
    806             $yc = round($this->posy*$img->height);
    807         }
    808         else {
    809             $yc = $this->posy ;
    810         }
    811 
    812         if( $this->radius <= 1 ) {
    813             $width = floor($this->radius*min($img->width,$img->height));
    814             // Make sure that the pie doesn't overflow the image border
    815             // The 0.9 factor is simply an extra margin to leave some space
    816             // between the pie an the border of the image.
    817             $width = min($width,min($xc*0.9,($yc*90/$this->angle-$width/4)*0.9));
    818         }
    819         else {
    820             $width = $this->radius * ($aaoption === 1 ? 2 : 1 ) ;
    821         }
    822 
    823         // Add a sanity check for width
    824         if( $width < 1 ) {
    825             JpGraphError::RaiseL(14007);//("Width for 3D Pie is 0. Specify a size > 0");
    826         }
    827 
    828         // Establish a thickness. By default the thickness is a fifth of the
    829         // pie slice width (=pie radius) but since the perspective depends
    830         // on the inclination angle we use some heuristics to make the edge
    831         // slightly thicker the less the angle.
    832 
    833         // Has user specified an absolute thickness? In that case use
    834         // that instead
    835 
    836         if( $this->iThickness ) {
    837             $thick = $this->iThickness;
    838             $thick *= ($aaoption === 1 ? 2 : 1 );
    839         }
    840         else {
    841             $thick = $width/12;
    842         }
    843         $a = $this->angle;
    844        
    845         if( $a <= 30 ) $thick *= 1.6;
    846         elseif( $a <= 40 ) $thick *= 1.4;
    847         elseif( $a <= 50 ) $thick *= 1.2;
    848         elseif( $a <= 60 ) $thick *= 1.0;
    849         elseif( $a <= 70 ) $thick *= 0.8;
    850         elseif( $a <= 80 ) $thick *= 0.7;
    851         else $thick *= 0.6;
    852 
    853         $thick = floor($thick);
    854 
    855         if( $this->explode_all ) {
    856             for($i=0; $i < $n; ++$i)
    857                 $this->explode_radius[$i]=$this->explode_r;
    858         }
    859 
    860         $this->Pie3D($aaoption,$img,$this->data, $ca, $xc, $yc, $width, $this->angle,
    861         $thick, 0.65, $this->startangle, $this->edgecolor, $this->edgeweight);
    862 
    863         // Adjust title position
    864         if( $aaoption != 1 ) {
    865             $this->title->SetPos($xc,$yc-$this->title->GetFontHeight($img)-$width/2-$this->title->margin,         "center","bottom");
    866             $this->title->Stroke($img);
    867         }
    868     }
    869 
    870     //---------------
    871     // PRIVATE METHODS
     784        $n = count($this->data);
     785
     786        // If user hasn't set the colors use the theme array
     787        if( $this->setslicecolors==null ) {
     788            $colors = array_keys($img->rgb->rgb_table);
     789            sort($colors);     
     790            $idx_a=$this->themearr[$this->theme];       
     791            $ca = array();
     792            $m = count($idx_a);
     793            for($i=0; $i < $m; ++$i)
     794                $ca[$i] = $colors[$idx_a[$i]];
     795            $ca = array_reverse(array_slice($ca,0,$n));
     796        }
     797        else {
     798            $ca = $this->setslicecolors;
     799        }
     800       
     801
     802        if( $this->posx <= 1 && $this->posx > 0 )
     803            $xc = round($this->posx*$img->width);
     804        else
     805            $xc = $this->posx ;
     806       
     807        if( $this->posy <= 1 && $this->posy > 0 )
     808            $yc = round($this->posy*$img->height);
     809        else
     810            $yc = $this->posy ;
     811                       
     812        if( $this->radius <= 1 ) {
     813            $width = floor($this->radius*min($img->width,$img->height));
     814            // Make sure that the pie doesn't overflow the image border
     815            // The 0.9 factor is simply an extra margin to leave some space
     816            // between the pie an the border of the image.
     817            $width = min($width,min($xc*0.9,($yc*90/$this->angle-$width/4)*0.9));
     818        }
     819        else {
     820            $width = $this->radius * ($aaoption === 1 ? 2 : 1 ) ;
     821        }
     822
     823        // Add a sanity check for width
     824        if( $width < 1 ) {
     825            JpGraphError::RaiseL(14007);//("Width for 3D Pie is 0. Specify a size > 0");
     826        }
     827
     828        // Establish a thickness. By default the thickness is a fifth of the
     829        // pie slice width (=pie radius) but since the perspective depends
     830        // on the inclination angle we use some heuristics to make the edge
     831        // slightly thicker the less the angle.
     832       
     833        // Has user specified an absolute thickness? In that case use
     834        // that instead
     835
     836        if( $this->iThickness ) {
     837          $thick = $this->iThickness;
     838          $thick *= ($aaoption === 1 ? 2 : 1 );
     839        }
     840        else
     841          $thick = $width/12;
     842        $a = $this->angle;
     843        if( $a <= 30 ) $thick *= 1.6;
     844        elseif( $a <= 40 ) $thick *= 1.4;
     845        elseif( $a <= 50 ) $thick *= 1.2;
     846        elseif( $a <= 60 ) $thick *= 1.0;
     847        elseif( $a <= 70 ) $thick *= 0.8;
     848        elseif( $a <= 80 ) $thick *= 0.7;
     849        else $thick *= 0.6;
     850
     851        $thick = floor($thick);
     852
     853        if( $this->explode_all )
     854            for($i=0; $i < $n; ++$i)
     855                $this->explode_radius[$i]=$this->explode_r;
     856
     857        $this->Pie3D($aaoption,$img,$this->data, $ca, $xc, $yc, $width, $this->angle,
     858                     $thick, 0.65, $this->startangle, $this->edgecolor, $this->edgeweight);
     859
     860        // Adjust title position
     861        if( $aaoption != 1 ) {
     862            $this->title->SetPos($xc,$yc-$this->title->GetFontHeight($img)-$width/2-$this->title->margin,                             "center","bottom");
     863            $this->title->Stroke($img);
     864        }
     865    }
     866
     867//---------------
     868// PRIVATE METHODS     
    872869
    873870    // Position the labels of each slice
    874871    function StrokeLabels($label,$img,$a,$xp,$yp,$z) {
    875         $this->value->halign="left";
    876         $this->value->valign="top";
    877 
    878         // Position the axis title.
    879         // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
    880         // that intersects with the extension of the corresponding axis. The code looks a little
    881         // bit messy but this is really the only way of having a reasonable position of the
    882         // axis titles.
    883         $this->value->ApplyFont($img);
    884         $h=$img->GetTextHeight($label);
    885         // For numeric values the format of the display value
    886         // must be taken into account
    887         if( is_numeric($label) ) {
    888             if( $label >= 0 ) {
    889                 $w=$img->GetTextWidth(sprintf($this->value->format,$label));
    890             }
    891             else {
    892                 $w=$img->GetTextWidth(sprintf($this->value->negformat,$label));
    893             }
    894         }
    895         else {
    896             $w=$img->GetTextWidth($label);
    897         }
    898        
    899         while( $a > 2*M_PI ) {
    900             $a -= 2*M_PI;
    901         }
    902        
    903         if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0;
    904         if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI;
    905         if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1;
    906         if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI);
    907 
    908         if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI;
    909         if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI);
    910         if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1;
    911         if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI);
    912         if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0;
    913 
    914         $x = round($xp-$dx*$w);
    915         $y = round($yp-$dy*$h);
    916 
    917         // Mark anchor point for debugging
    918         /*
    919         $img->SetColor('red');
    920         $img->Line($xp-10,$yp,$xp+10,$yp);
    921         $img->Line($xp,$yp-10,$xp,$yp+10);
    922         */
    923 
    924         $oldmargin = $this->value->margin;
    925         $this->value->margin=0;
    926         $this->value->Stroke($img,$label,$x,$y);
    927         $this->value->margin=$oldmargin;
    928 
    929     }
     872        $this->value->halign="left";
     873        $this->value->valign="top";
     874
     875        // Position the axis title.
     876        // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
     877        // that intersects with the extension of the corresponding axis. The code looks a little
     878        // bit messy but this is really the only way of having a reasonable position of the
     879        // axis titles.
     880        $this->value->ApplyFont($img);
     881        $h=$img->GetTextHeight($label);
     882        // For numeric values the format of the display value
     883        // must be taken into account
     884        if( is_numeric($label) ) {
     885            if( $label >= 0 )
     886                $w=$img->GetTextWidth(sprintf($this->value->format,$label));
     887            else
     888                $w=$img->GetTextWidth(sprintf($this->value->negformat,$label));
     889        }
     890        else
     891            $w=$img->GetTextWidth($label);
     892        while( $a > 2*M_PI ) $a -= 2*M_PI;
     893        if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0;
     894        if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI;
     895        if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1;
     896        if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI);
     897               
     898        if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI;
     899        if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI);
     900        if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1;
     901        if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI);
     902        if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0;
     903       
     904        $x = round($xp-$dx*$w);
     905        $y = round($yp-$dy*$h);
     906
     907       
     908        // Mark anchor point for debugging
     909        /*
     910        $img->SetColor('red');
     911        $img->Line($xp-10,$yp,$xp+10,$yp);
     912        $img->Line($xp,$yp-10,$xp,$yp+10);
     913        */
     914        $oldmargin = $this->value->margin;
     915        $this->value->margin=0;
     916        $this->value->Stroke($img,$label,$x,$y);
     917        $this->value->margin=$oldmargin;
     918
     919    }   
    930920} // Class
    931921
  • trunk/client/modules/Elezioni/grafici/jpgraph_plotband.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_PLOTBAND.PHP
    4 // Description: PHP4 Graph Plotting library. Extension module.
    5 // Created:     2004-02-18
    6 // Ver:         $Id: jpgraph_plotband.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        JPGRAPH_PLOTBAND.PHP
     4// Description: PHP4 Graph Plotting library. Extension module.
     5// Created:     2004-02-18
     6// Ver:         $Id: jpgraph_plotband.php 1091 2009-01-18 22:57:40Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
    1111// Constants for types of static bands in plot area
    12 define("BAND_RDIAG",1); // Right diagonal lines
     12define("BAND_RDIAG",1); // Right diagonal lines
    1313define("BAND_LDIAG",2); // Left diagonal lines
    1414define("BAND_SOLID",3); // Solid one color
     
    2424    public $x,$y,$w,$h;
    2525    public $xe, $ye;
    26     function __construct($aX,$aY,$aWidth,$aHeight) {
    27         $this->x=$aX;
    28         $this->y=$aY;
    29         $this->w=$aWidth;
    30         $this->h=$aHeight;
    31         $this->xe=$aX+$aWidth-1;
    32         $this->ye=$aY+$aHeight-1;
     26    function Rectangle($aX,$aY,$aWidth,$aHeight) {
     27        $this->x=$aX;
     28        $this->y=$aY;
     29        $this->w=$aWidth;
     30        $this->h=$aHeight;
     31        $this->xe=$aX+$aWidth-1;
     32        $this->ye=$aY+$aHeight-1;
    3333    }
    3434}
     
    4646    protected $rect=null;
    4747    protected $doframe=true;
    48     protected $linespacing; // Line spacing in pixels
     48    protected $linespacing;     // Line spacing in pixels
    4949    protected $iBackgroundColor=-1;  // Default is no background fill
    50 
    51     function __construct($aColor,$aWeight=1) {
    52         $this->color = $aColor;
    53         $this->weight = $aWeight;
     50       
     51    function RectPattern($aColor,$aWeight=1) {
     52        $this->color = $aColor;
     53        $this->weight = $aWeight;               
    5454    }
    5555
    5656    function SetBackground($aBackgroundColor) {
    57         $this->iBackgroundColor=$aBackgroundColor;
     57        $this->iBackgroundColor=$aBackgroundColor;
    5858    }
    5959
    6060    function SetPos($aRect) {
    61         $this->rect = $aRect;
    62     }
    63 
     61        $this->rect = $aRect;
     62    }
     63       
    6464    function ShowFrame($aShow=true) {
    65         $this->doframe=$aShow;
     65        $this->doframe=$aShow;
    6666    }
    6767
    6868    function SetDensity($aDens) {
    69         if( $aDens < 1 || $aDens > 100 )
    70         JpGraphError::RaiseL(16001,$aDens);
    71         //(" Desity for pattern must be between 1 and 100. (You tried $aDens)");
    72         // 1% corresponds to linespacing=50
    73         // 100 % corresponds to linespacing 1
    74         $this->linespacing = floor(((100-$aDens)/100.0)*50)+1;
     69        if( $aDens < 1 || $aDens > 100 )
     70            JpGraphError::RaiseL(16001,$aDens);
     71//(" Desity for pattern must be between 1 and 100. (You tried $aDens)");
     72        // 1% corresponds to linespacing=50
     73        // 100 % corresponds to linespacing 1
     74        $this->linespacing = floor(((100-$aDens)/100.0)*50)+1;
    7575
    7676    }
    7777
    7878    function Stroke($aImg) {
    79         if( $this->rect == null )
    80         JpGraphError::RaiseL(16002);
    81         //(" No positions specified for pattern.");
    82 
    83         if( !(is_numeric($this->iBackgroundColor) && $this->iBackgroundColor==-1) ) {
    84             $aImg->SetColor($this->iBackgroundColor);
    85             $aImg->FilledRectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
    86         }
    87 
    88         $aImg->SetColor($this->color);
    89         $aImg->SetLineWeight($this->weight);
    90 
    91         // Virtual function implemented by subclass
    92         $this->DoPattern($aImg);
    93 
    94         // Frame around the pattern area
    95         if( $this->doframe )
    96         $aImg->Rectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
     79        if( $this->rect == null )
     80            JpGraphError::RaiseL(16002);
     81//(" No positions specified for pattern.");
     82
     83        if( !(is_numeric($this->iBackgroundColor) && $this->iBackgroundColor==-1) ) {
     84            $aImg->SetColor($this->iBackgroundColor);
     85            $aImg->FilledRectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
     86        }
     87
     88        $aImg->SetColor($this->color);
     89        $aImg->SetLineWeight($this->weight);
     90
     91        // Virtual function implemented by subclass
     92        $this->DoPattern($aImg);
     93
     94        // Frame around the pattern area
     95        if( $this->doframe )
     96            $aImg->Rectangle($this->rect->x,$this->rect->y,$this->rect->xe,$this->rect->ye);
    9797    }
    9898
     
    106106class RectPatternSolid extends RectPattern {
    107107
    108     function __construct($aColor="black",$aWeight=1) {
    109         parent::__construct($aColor,$aWeight);
    110     }
    111 
    112     function DoPattern($aImg) {
    113         $aImg->SetColor($this->color);
    114         $aImg->FilledRectangle($this->rect->x,$this->rect->y,
    115         $this->rect->xe,$this->rect->ye);
     108    function RectPatternSolid($aColor="black",$aWeight=1) {
     109        parent::RectPattern($aColor,$aWeight);
     110    }
     111
     112    function DoPattern($aImg) {
     113        $aImg->SetColor($this->color);
     114        $aImg->FilledRectangle($this->rect->x,$this->rect->y,
     115                               $this->rect->xe,$this->rect->ye);
    116116    }
    117117}
     
    122122//=====================================================================
    123123class RectPatternHor extends RectPattern {
    124 
    125     function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) {
    126         parent::__construct($aColor,$aWeight);
    127         $this->linespacing = $aLineSpacing;
    128     }
    129 
    130     function DoPattern($aImg) {
    131         $x0 = $this->rect->x;
    132         $x1 = $this->rect->xe;
    133         $y = $this->rect->y;
    134         while( $y < $this->rect->ye ) {
    135             $aImg->Line($x0,$y,$x1,$y);
    136             $y += $this->linespacing;
    137         }
     124               
     125    function RectPatternHor($aColor="black",$aWeight=1,$aLineSpacing=7) {
     126        parent::RectPattern($aColor,$aWeight);
     127        $this->linespacing = $aLineSpacing;
     128    }
     129               
     130    function DoPattern($aImg) {
     131        $x0 = $this->rect->x;           
     132        $x1 = $this->rect->xe;
     133        $y = $this->rect->y;
     134        while( $y < $this->rect->ye ) {
     135            $aImg->Line($x0,$y,$x1,$y);
     136            $y += $this->linespacing;
     137        }
    138138    }
    139139}
     
    144144//=====================================================================
    145145class RectPatternVert extends RectPattern {
    146 
    147     function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) {
    148         parent::__construct($aColor,$aWeight);
    149         $this->linespacing = $aLineSpacing;
     146               
     147    function RectPatternVert($aColor="black",$aWeight=1,$aLineSpacing=7) {
     148        parent::RectPattern($aColor,$aWeight);
     149        $this->linespacing = $aLineSpacing;
    150150    }
    151151
     
    154154    //
    155155    function DoPattern($aImg) {
    156         $x = $this->rect->x;
    157         $y0 = $this->rect->y;
    158         $y1 = $this->rect->ye;
    159         while( $x < $this->rect->xe ) {
    160             $aImg->Line($x,$y0,$x,$y1);
    161             $x += $this->linespacing;
    162         }
     156        $x = $this->rect->x;           
     157        $y0 = $this->rect->y;
     158        $y1 = $this->rect->ye;
     159        while( $x < $this->rect->xe ) {
     160            $aImg->Line($x,$y0,$x,$y1);
     161            $x += $this->linespacing;
     162        }
    163163    }
    164164}
     
    170170//=====================================================================
    171171class RectPatternRDiag extends RectPattern {
    172 
    173     function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) {
    174         parent::__construct($aColor,$aWeight);
    175         $this->linespacing = $aLineSpacing;
    176     }
    177 
    178     function DoPattern($aImg) {
    179         //  --------------------
    180         //  | /   /   /   /   /|
    181         //  |/   /   /   /   / |
    182         //  |   /   /   /   /  |
    183         //  --------------------
    184         $xe = $this->rect->xe;
    185         $ye = $this->rect->ye;
    186         $x0 = $this->rect->x + round($this->linespacing/2);
    187         $y0 = $this->rect->y;
    188         $x1 = $this->rect->x;
    189         $y1 = $this->rect->y + round($this->linespacing/2);
    190 
    191         while($x0<=$xe && $y1<=$ye) {
    192             $aImg->Line($x0,$y0,$x1,$y1);
    193             $x0 += $this->linespacing;
    194             $y1 += $this->linespacing;
    195         }
    196 
    197         if( $xe-$x1 > $ye-$y0 ) {
    198             // Width larger than height
    199             $x1 = $this->rect->x + ($y1-$ye);
    200             $y1 = $ye;
    201             $y0 = $this->rect->y;
    202             while( $x0 <= $xe ) {
    203                 $aImg->Line($x0,$y0,$x1,$y1);
    204                 $x0 += $this->linespacing;
    205                 $x1 += $this->linespacing;
    206             }
    207             
    208             $y0=$this->rect->y + ($x0-$xe);
    209             $x0=$xe;
    210         }
    211         else {
    212             // Height larger than width
    213             $diff = $x0-$xe;
    214             $y0 = $diff+$this->rect->y;
    215             $x0 = $xe;
    216             $x1 = $this->rect->x;
    217             while( $y1 <= $ye ) {
    218                 $aImg->Line($x0,$y0,$x1,$y1);
    219                 $y1 += $this->linespacing;
    220                 $y0 += $this->linespacing;
    221             }
    222             
    223             $diff = $y1-$ye;
    224             $y1 = $ye;
    225             $x1 = $diff + $this->rect->x;
    226         }
    227 
    228         while( $y0 <= $ye ) {
    229             $aImg->Line($x0,$y0,$x1,$y1);
    230             $y0 += $this->linespacing;
    231             $x1 += $this->linespacing;
    232         }
    233     }
    234 }
    235 
     172               
     173    function RectPatternRDiag($aColor="black",$aWeight=1,$aLineSpacing=12) {
     174        parent::RectPattern($aColor,$aWeight);
     175        $this->linespacing = $aLineSpacing;
     176    }
     177
     178    function DoPattern($aImg) {
     179        //  --------------------
     180        //  | /   /   /   /   /|
     181        //  |/   /   /   /   / |
     182        //  |   /   /   /   /  |
     183        //  --------------------
     184        $xe = $this->rect->xe;
     185        $ye = $this->rect->ye;
     186        $x0 = $this->rect->x + round($this->linespacing/2);
     187        $y0 = $this->rect->y;
     188        $x1 = $this->rect->x;
     189        $y1 = $this->rect->y + round($this->linespacing/2);
     190
     191        while($x0<=$xe && $y1<=$ye) {
     192            $aImg->Line($x0,$y0,$x1,$y1);
     193            $x0 += $this->linespacing;
     194            $y1 += $this->linespacing;
     195        }
     196
     197        if( $xe-$x1 > $ye-$y0 ) {
     198            // Width larger than height
     199            $x1 = $this->rect->x + ($y1-$ye);
     200            $y1 = $ye;
     201            $y0 = $this->rect->y;
     202            while( $x0 <= $xe ) {
     203                $aImg->Line($x0,$y0,$x1,$y1);
     204                $x0 += $this->linespacing;
     205                $x1 += $this->linespacing;
     206            }
     207           
     208            $y0=$this->rect->y + ($x0-$xe);
     209            $x0=$xe;
     210        }
     211        else {
     212            // Height larger than width
     213            $diff = $x0-$xe;
     214            $y0 = $diff+$this->rect->y;
     215            $x0 = $xe;
     216            $x1 = $this->rect->x;
     217            while( $y1 <= $ye ) {
     218                $aImg->Line($x0,$y0,$x1,$y1);
     219                $y1 += $this->linespacing;
     220                $y0 += $this->linespacing;
     221            }
     222           
     223            $diff = $y1-$ye;
     224            $y1 = $ye;
     225            $x1 = $diff + $this->rect->x;
     226        }
     227
     228        while( $y0 <= $ye ) {
     229            $aImg->Line($x0,$y0,$x1,$y1);
     230            $y0 += $this->linespacing;         
     231            $x1 += $this->linespacing;
     232        }
     233    }
     234}
     235 
    236236//=====================================================================
    237237// Class RectPatternLDiag
     
    239239//=====================================================================
    240240class RectPatternLDiag extends RectPattern {
    241 
    242     function __construct($aColor="black",$aWeight=1,$aLineSpacing=12) {
    243         $this->linespacing = $aLineSpacing;
    244         parent::__construct($aColor,$aWeight);
    245     }
    246 
    247     function DoPattern($aImg) {
    248         //  --------------------
    249         //  |\   \   \   \   \ |
    250         //  | \   \   \   \   \|
    251         //  |  \   \   \   \   |
    252         //  |------------------|
    253         $xe = $this->rect->xe;
    254         $ye = $this->rect->ye;
    255         $x0 = $this->rect->x + round($this->linespacing/2);
    256         $y0 = $this->rect->ye;
    257         $x1 = $this->rect->x;
    258         $y1 = $this->rect->ye - round($this->linespacing/2);
    259 
    260         while($x0<=$xe && $y1>=$this->rect->y) {
    261             $aImg->Line($x0,$y0,$x1,$y1);
    262             $x0 += $this->linespacing;
    263             $y1 -= $this->linespacing;
    264         }
    265         if( $xe-$x1 > $ye-$this->rect->y ) {
    266             // Width larger than height
    267             $x1 = $this->rect->x + ($this->rect->y-$y1);
    268             $y0=$ye; $y1=$this->rect->y;
    269             while( $x0 <= $xe ) {
    270                 $aImg->Line($x0,$y0,$x1,$y1);
    271                 $x0 += $this->linespacing;
    272                 $x1 += $this->linespacing;
    273             }
    274             
    275             $y0=$this->rect->ye - ($x0-$xe);
    276             $x0=$xe;
    277         }
    278         else {
    279             // Height larger than width
    280             $diff = $x0-$xe;
    281             $y0 = $ye-$diff;
    282             $x0 = $xe;
    283             while( $y1 >= $this->rect->y ) {
    284                 $aImg->Line($x0,$y0,$x1,$y1);
    285                 $y0 -= $this->linespacing;
    286                 $y1 -= $this->linespacing;
    287             }
    288             $diff = $this->rect->y - $y1;
    289             $x1 = $this->rect->x + $diff;
    290             $y1 = $this->rect->y;
    291         }
    292         while( $y0 >= $this->rect->y ) {
    293             $aImg->Line($x0,$y0,$x1,$y1);
    294             $y0 -= $this->linespacing;
    295             $x1 += $this->linespacing;
    296         }
     241               
     242    function RectPatternLDiag($aColor="black",$aWeight=1,$aLineSpacing=12) {
     243        $this->linespacing = $aLineSpacing;
     244        parent::RectPattern($aColor,$aWeight);
     245    }
     246
     247    function DoPattern($aImg) {
     248        //  --------------------
     249        //  |\   \   \   \   \ |
     250        //  | \   \   \   \   \|
     251        //  |  \   \   \   \   |
     252        //  |------------------|
     253        $xe = $this->rect->xe;
     254        $ye = $this->rect->ye;
     255        $x0 = $this->rect->x + round($this->linespacing/2);
     256        $y0 = $this->rect->ye;
     257        $x1 = $this->rect->x;
     258        $y1 = $this->rect->ye - round($this->linespacing/2);
     259
     260        while($x0<=$xe && $y1>=$this->rect->y) {
     261            $aImg->Line($x0,$y0,$x1,$y1);
     262            $x0 += $this->linespacing;
     263            $y1 -= $this->linespacing;
     264        }
     265        if( $xe-$x1 > $ye-$this->rect->y ) {
     266            // Width larger than height
     267            $x1 = $this->rect->x + ($this->rect->y-$y1);
     268            $y0=$ye; $y1=$this->rect->y;
     269            while( $x0 <= $xe ) {
     270                $aImg->Line($x0,$y0,$x1,$y1);
     271                $x0 += $this->linespacing;
     272                $x1 += $this->linespacing;
     273            }
     274           
     275            $y0=$this->rect->ye - ($x0-$xe);
     276            $x0=$xe;
     277        }
     278        else {
     279            // Height larger than width
     280            $diff = $x0-$xe;
     281            $y0 = $ye-$diff;
     282            $x0 = $xe;
     283            while( $y1 >= $this->rect->y ) {
     284                $aImg->Line($x0,$y0,$x1,$y1);
     285                $y0 -= $this->linespacing;
     286                $y1 -= $this->linespacing;
     287            }       
     288            $diff = $this->rect->y - $y1;
     289            $x1 = $this->rect->x + $diff;
     290            $y1 = $this->rect->y;
     291        }
     292        while( $y0 >= $this->rect->y ) {
     293            $aImg->Line($x0,$y0,$x1,$y1);
     294            $y0 -= $this->linespacing;
     295            $x1 += $this->linespacing;
     296        }
    297297    }
    298298}
     
    308308    // converge.
    309309
    310     function __construct($aColor="black",$aWeight=1) {
    311         parent::__construct($aColor,$aWeight);
    312         $this->SetDensity(10);  // Slightly larger default
     310    function RectPattern3DPlane($aColor="black",$aWeight=1) {
     311        parent::RectPattern($aColor,$aWeight);
     312        $this->SetDensity(10);  // Slightly larger default
    313313    }
    314314
    315315    function SetHorizon($aHorizon) {
    316         $this->alpha=$aHorizon;
    317     }
    318 
    319     function DoPattern($aImg) {
    320         // "Fake" a nice 3D grid-effect.
    321         $x0 = $this->rect->x + $this->rect->w/2;
    322         $y0 = $this->rect->y;
    323         $x1 = $x0;
    324         $y1 = $this->rect->ye;
    325         $x0_right = $x0;
    326         $x1_right = $x1;
    327 
    328         // BTW "apa" means monkey in Swedish but is really a shortform for
    329         // "alpha+a" which was the labels I used on paper when I derived the
    330         // geometric to get the 3D perspective right.
    331         // $apa is the height of the bounding rectangle plus the distance to the
    332         // artifical horizon (alpha)
    333         $apa = $this->rect->h + $this->alpha;
    334 
    335         // Three cases and three loops
    336         // 1) The endpoint of the line ends on the bottom line
    337         // 2) The endpoint ends on the side
    338         // 3) Horizontal lines
    339 
    340         // Endpoint falls on bottom line
    341         $middle=$this->rect->x + $this->rect->w/2;
    342         $dist=$this->linespacing;
    343         $factor=$this->alpha /($apa);
    344         while($x1>$this->rect->x) {
    345             $aImg->Line($x0,$y0,$x1,$y1);
    346             $aImg->Line($x0_right,$y0,$x1_right,$y1);
    347             $x1 = $middle - $dist;
    348             $x0 = $middle - $dist * $factor;
    349             $x1_right = $middle + $dist;
    350             $x0_right =  $middle + $dist * $factor;
    351             $dist += $this->linespacing;
    352         }
    353 
    354         // Endpoint falls on sides
    355         $dist -= $this->linespacing;
    356         $d=$this->rect->w/2;
    357         $c = $apa - $d*$apa/$dist;
    358         while( $x0>$this->rect->x ) {
    359             $aImg->Line($x0,$y0,$this->rect->x,$this->rect->ye-$c);
    360             $aImg->Line($x0_right,$y0,$this->rect->xe,$this->rect->ye-$c);
    361             $dist += $this->linespacing;
    362             $x0 = $middle - $dist * $factor;
    363             $x1 = $middle - $dist;
    364             $x0_right =  $middle + $dist * $factor;
    365             $c = $apa - $d*$apa/$dist;
    366         }
    367 
    368         // Horizontal lines
    369         // They need some serious consideration since they are a function
    370         // of perspective depth (alpha) and density (linespacing)
    371         $x0=$this->rect->x;
    372         $x1=$this->rect->xe;
    373         $y=$this->rect->ye;
    374 
    375         // The first line is drawn directly. Makes the loop below slightly
    376         // more readable.
    377         $aImg->Line($x0,$y,$x1,$y);
    378         $hls = $this->linespacing;
    379 
    380         // A correction factor for vertical "brick" line spacing to account for
    381         // a) the difference in number of pixels hor vs vert
    382         // b) visual apperance to make the first layer of "bricks" look more
    383         // square.
    384         $vls = $this->linespacing*0.6;
    385 
    386         $ds = $hls*($apa-$vls)/$apa;
    387         // Get the slope for the "perspective line" going from bottom right
    388         // corner to top left corner of the "first" brick.
    389 
    390         // Uncomment the following lines if you want to get a visual understanding
    391         // of what this helpline does. BTW this mimics the way you would get the
    392         // perspective right when drawing on paper.
    393         /*
    394         $x0 = $middle;
    395         $y0 = $this->rect->ye;
    396         $len=floor(($this->rect->ye-$this->rect->y)/$vls);
    397         $x1 = $middle+round($len*$ds);
    398         $y1 = $this->rect->ye-$len*$vls;
    399         $aImg->PushColor("red");
    400         $aImg->Line($x0,$y0,$x1,$y1);
    401         $aImg->PopColor();
    402         */
    403 
    404         $y -= $vls;
    405         $k=($this->rect->ye-($this->rect->ye-$vls))/($middle-($middle-$ds));
    406         $dist = $hls;
    407         while( $y>$this->rect->y ) {
    408             $aImg->Line($this->rect->x,$y,$this->rect->xe,$y);
    409             $adj = $k*$dist/(1+$dist*$k/$apa);
    410             if( $adj < 2 ) $adj=1;
    411             $y = $this->rect->ye - round($adj);
    412             $dist += $hls;
    413         }
     316        $this->alpha=$aHorizon;
     317    }
     318       
     319    function DoPattern($aImg) {
     320        // "Fake" a nice 3D grid-effect.
     321        $x0 = $this->rect->x + $this->rect->w/2;
     322        $y0 = $this->rect->y;
     323        $x1 = $x0;
     324        $y1 = $this->rect->ye;
     325        $x0_right = $x0;
     326        $x1_right = $x1;
     327
     328        // BTW "apa" means monkey in Swedish but is really a shortform for
     329        // "alpha+a" which was the labels I used on paper when I derived the
     330        // geometric to get the 3D perspective right.
     331        // $apa is the height of the bounding rectangle plus the distance to the
     332        // artifical horizon (alpha)
     333        $apa = $this->rect->h + $this->alpha;
     334
     335        // Three cases and three loops
     336        // 1) The endpoint of the line ends on the bottom line
     337        // 2) The endpoint ends on the side
     338        // 3) Horizontal lines
     339
     340        // Endpoint falls on bottom line
     341        $middle=$this->rect->x + $this->rect->w/2;
     342        $dist=$this->linespacing;
     343        $factor=$this->alpha /($apa);
     344        while($x1>$this->rect->x) {
     345            $aImg->Line($x0,$y0,$x1,$y1);
     346            $aImg->Line($x0_right,$y0,$x1_right,$y1);
     347            $x1 = $middle - $dist;
     348            $x0 = $middle - $dist * $factor;
     349            $x1_right = $middle + $dist;
     350            $x0_right =  $middle + $dist * $factor;
     351            $dist += $this->linespacing;
     352        }
     353
     354        // Endpoint falls on sides
     355        $dist -= $this->linespacing;
     356        $d=$this->rect->w/2;
     357        $c = $apa - $d*$apa/$dist;
     358        while( $x0>$this->rect->x ) {
     359            $aImg->Line($x0,$y0,$this->rect->x,$this->rect->ye-$c);
     360            $aImg->Line($x0_right,$y0,$this->rect->xe,$this->rect->ye-$c);
     361            $dist += $this->linespacing;                       
     362            $x0 = $middle - $dist * $factor;
     363            $x1 = $middle - $dist;
     364            $x0_right =  $middle + $dist * $factor;                     
     365            $c = $apa - $d*$apa/$dist;
     366        }               
     367               
     368        // Horizontal lines
     369        // They need some serious consideration since they are a function
     370        // of perspective depth (alpha) and density (linespacing)
     371        $x0=$this->rect->x;
     372        $x1=$this->rect->xe;
     373        $y=$this->rect->ye;
     374               
     375        // The first line is drawn directly. Makes the loop below slightly
     376        // more readable.
     377        $aImg->Line($x0,$y,$x1,$y);
     378        $hls = $this->linespacing;
     379               
     380        // A correction factor for vertical "brick" line spacing to account for
     381        // a) the difference in number of pixels hor vs vert
     382        // b) visual apperance to make the first layer of "bricks" look more
     383        // square.
     384        $vls = $this->linespacing*0.6;
     385               
     386        $ds = $hls*($apa-$vls)/$apa;
     387        // Get the slope for the "perspective line" going from bottom right
     388        // corner to top left corner of the "first" brick.
     389               
     390        // Uncomment the following lines if you want to get a visual understanding
     391        // of what this helpline does. BTW this mimics the way you would get the
     392        // perspective right when drawing on paper.
     393        /*
     394          $x0 = $middle;
     395          $y0 = $this->rect->ye;
     396          $len=floor(($this->rect->ye-$this->rect->y)/$vls);
     397          $x1 = $middle+round($len*$ds);
     398          $y1 = $this->rect->ye-$len*$vls;
     399          $aImg->PushColor("red");
     400          $aImg->Line($x0,$y0,$x1,$y1);
     401          $aImg->PopColor();
     402        */
     403               
     404        $y -= $vls;             
     405        $k=($this->rect->ye-($this->rect->ye-$vls))/($middle-($middle-$ds));
     406        $dist = $hls;
     407        while( $y>$this->rect->y ) {
     408            $aImg->Line($this->rect->x,$y,$this->rect->xe,$y);
     409            $adj = $k*$dist/(1+$dist*$k/$apa);
     410            if( $adj < 2 ) $adj=1;
     411            $y = $this->rect->ye - round($adj);
     412            $dist += $hls;
     413        }
    414414    }
    415415}
     
    422422    private $vert=null;
    423423    private $hor=null;
    424     function __construct($aColor="black",$aWeight=1) {
    425         parent::__construct($aColor,$aWeight);
    426         $this->vert = new RectPatternVert($aColor,$aWeight);
    427         $this->hor  = new RectPatternHor($aColor,$aWeight);
     424    function RectPatternCross($aColor="black",$aWeight=1) {
     425        parent::RectPattern($aColor,$aWeight);
     426        $this->vert = new RectPatternVert($aColor,$aWeight);
     427        $this->hor  = new RectPatternHor($aColor,$aWeight);
    428428    }
    429429
    430430    function SetOrder($aDepth) {
    431         $this->vert->SetOrder($aDepth);
    432         $this->hor->SetOrder($aDepth);
     431        $this->vert->SetOrder($aDepth);
     432        $this->hor->SetOrder($aDepth);
    433433    }
    434434
    435435    function SetPos($aRect) {
    436         parent::SetPos($aRect);
    437         $this->vert->SetPos($aRect);
    438         $this->hor->SetPos($aRect);
     436        parent::SetPos($aRect);
     437        $this->vert->SetPos($aRect);
     438        $this->hor->SetPos($aRect);
    439439    }
    440440
    441441    function SetDensity($aDens) {
    442         $this->vert->SetDensity($aDens);
    443         $this->hor->SetDensity($aDens);
    444     }
    445 
    446     function DoPattern($aImg) {
    447         $this->vert->DoPattern($aImg);
    448         $this->hor->DoPattern($aImg);
     442        $this->vert->SetDensity($aDens);
     443        $this->hor->SetDensity($aDens);
     444    }
     445
     446    function DoPattern($aImg) {
     447        $this->vert->DoPattern($aImg);
     448        $this->hor->DoPattern($aImg);
    449449    }
    450450}
     
    458458    private $left=null;
    459459    private $right=null;
    460     function __construct($aColor="black",$aWeight=1) {
    461         parent::__construct($aColor,$aWeight);
    462         $this->right = new RectPatternRDiag($aColor,$aWeight);
    463         $this->left  = new RectPatternLDiag($aColor,$aWeight);
     460    function RectPatternDiagCross($aColor="black",$aWeight=1) {
     461        parent::RectPattern($aColor,$aWeight);
     462        $this->right = new RectPatternRDiag($aColor,$aWeight);
     463        $this->left  = new RectPatternLDiag($aColor,$aWeight);
    464464    }
    465465
    466466    function SetOrder($aDepth) {
    467         $this->left->SetOrder($aDepth);
    468         $this->right->SetOrder($aDepth);
     467        $this->left->SetOrder($aDepth);
     468        $this->right->SetOrder($aDepth);
    469469    }
    470470
    471471    function SetPos($aRect) {
    472         parent::SetPos($aRect);
    473         $this->left->SetPos($aRect);
    474         $this->right->SetPos($aRect);
     472        parent::SetPos($aRect);
     473        $this->left->SetPos($aRect);
     474        $this->right->SetPos($aRect);
    475475    }
    476476
    477477    function SetDensity($aDens) {
    478         $this->left->SetDensity($aDens);
    479         $this->right->SetDensity($aDens);
    480     }
    481 
    482     function DoPattern($aImg) {
    483         $this->left->DoPattern($aImg);
    484         $this->right->DoPattern($aImg);
     478        $this->left->SetDensity($aDens);
     479        $this->right->SetDensity($aDens);
     480    }
     481
     482    function DoPattern($aImg) {
     483        $this->left->DoPattern($aImg);
     484        $this->right->DoPattern($aImg);
    485485    }
    486486
     
    489489//=====================================================================
    490490// Class RectPatternFactory
    491 // Factory class for rectangular pattern
     491// Factory class for rectangular pattern 
    492492//=====================================================================
    493493class RectPatternFactory {
    494     function __construct() {
    495         // Empty
     494    function RectPatternFactory() {
     495        // Empty
    496496    }
    497497    function Create($aPattern,$aColor,$aWeight=1) {
    498         switch($aPattern) {
    499             case BAND_RDIAG:
    500                 $obj =  new RectPatternRDiag($aColor,$aWeight);
    501                 break;
    502             case BAND_LDIAG:
    503                 $obj =  new RectPatternLDiag($aColor,$aWeight);
    504                 break;
    505             case BAND_SOLID:
    506                 $obj =  new RectPatternSolid($aColor,$aWeight);
    507                 break;
    508             case BAND_VLINE:
    509                 $obj =  new RectPatternVert($aColor,$aWeight);
    510                 break;
    511             case BAND_HLINE:
    512                 $obj =  new RectPatternHor($aColor,$aWeight);
    513                 break;
    514             case BAND_3DPLANE:
    515                 $obj =  new RectPattern3DPlane($aColor,$aWeight);
    516                 break;
    517             case BAND_HVCROSS:
    518                 $obj =  new RectPatternCross($aColor,$aWeight);
    519                 break;
    520             case BAND_DIAGCROSS:
    521                 $obj =  new RectPatternDiagCross($aColor,$aWeight);
    522                 break;
    523             default:
    524                 JpGraphError::RaiseL(16003,$aPattern);
    525                 //(" Unknown pattern specification ($aPattern)");
    526         }
    527         return $obj;
     498        switch($aPattern) {
     499            case BAND_RDIAG:
     500                $obj =  new RectPatternRDiag($aColor,$aWeight);
     501                break;
     502            case BAND_LDIAG:
     503                $obj =  new RectPatternLDiag($aColor,$aWeight);
     504                break;
     505            case BAND_SOLID:
     506                $obj =  new RectPatternSolid($aColor,$aWeight);
     507                break;
     508            case BAND_VLINE:
     509                $obj =  new RectPatternVert($aColor,$aWeight);
     510                break;
     511            case BAND_HLINE:
     512                $obj =  new RectPatternHor($aColor,$aWeight);
     513                break;
     514            case BAND_3DPLANE:
     515                $obj =  new RectPattern3DPlane($aColor,$aWeight);
     516                break;
     517            case BAND_HVCROSS:
     518                $obj =  new RectPatternCross($aColor,$aWeight);
     519                break;
     520            case BAND_DIAGCROSS:
     521                $obj =  new RectPatternDiagCross($aColor,$aWeight);
     522                break;
     523            default:
     524                JpGraphError::RaiseL(16003,$aPattern);
     525//(" Unknown pattern specification ($aPattern)");
     526        }
     527        return $obj;
    528528    }
    529529}
     
    541541    private $dir, $min, $max;
    542542
    543     function __construct($aDir,$aPattern,$aMin,$aMax,$aColor="black",$aWeight=1,$aDepth=DEPTH_BACK) {
    544         $f =  new RectPatternFactory();
    545         $this->prect = $f->Create($aPattern,$aColor,$aWeight);
    546         if( is_numeric($aMin) && is_numeric($aMax) && ($aMin > $aMax) )
    547         JpGraphError::RaiseL(16004);
    548         //('Min value for plotband is larger than specified max value. Please correct.');
    549         $this->dir = $aDir;
    550         $this->min = $aMin;
    551         $this->max = $aMax;
    552         $this->depth=$aDepth;
    553     }
    554 
     543    function PlotBand($aDir,$aPattern,$aMin,$aMax,$aColor="black",$aWeight=1,$aDepth=DEPTH_BACK) {
     544        $f =  new RectPatternFactory();
     545        $this->prect = $f->Create($aPattern,$aColor,$aWeight);
     546        if( is_numeric($aMin) && is_numeric($aMax) && ($aMin > $aMax) )
     547            JpGraphError::RaiseL(16004);
     548//('Min value for plotband is larger than specified max value. Please correct.');
     549        $this->dir = $aDir;
     550        $this->min = $aMin;
     551        $this->max = $aMax;
     552        $this->depth=$aDepth;
     553    }
     554       
    555555    // Set position. aRect contains absolute image coordinates
    556556    function SetPos($aRect) {
    557         assert( $this->prect != null ) ;
    558         $this->prect->SetPos($aRect);
    559     }
    560 
     557        assert( $this->prect != null ) ;
     558        $this->prect->SetPos($aRect);
     559    }
     560       
    561561    function ShowFrame($aFlag=true) {
    562         $this->prect->ShowFrame($aFlag);
     562        $this->prect->ShowFrame($aFlag);
    563563    }
    564564
    565565    // Set z-order. In front of pplot or in the back
    566566    function SetOrder($aDepth) {
    567         $this->depth=$aDepth;
    568     }
    569 
     567        $this->depth=$aDepth;
     568    }
     569       
    570570    function SetDensity($aDens) {
    571         $this->prect->SetDensity($aDens);
    572     }
    573 
     571        $this->prect->SetDensity($aDens);
     572    }
     573       
    574574    function GetDir() {
    575         return $this->dir;
    576     }
    577 
     575        return $this->dir;
     576    }
     577       
    578578    function GetMin() {
    579         return $this->min;
    580     }
    581 
     579        return $this->min;
     580    }
     581       
    582582    function GetMax() {
    583         return $this->max;
     583        return $this->max;
    584584    }
    585585
    586586    function PreStrokeAdjust($aGraph) {
    587         // Nothing to do
    588     }
    589 
     587        // Nothing to do
     588    }
     589       
    590590    // Display band
    591591    function Stroke($aImg,$aXScale,$aYScale) {
    592         assert( $this->prect != null ) ;
    593         if( $this->dir == HORIZONTAL ) {
    594             if( $this->min === 'min' ) $this->min = $aYScale->GetMinVal();
    595             if( $this->max === 'max' ) $this->max = $aYScale->GetMaxVal();
     592        assert( $this->prect != null ) ;
     593        if( $this->dir == HORIZONTAL ) {
     594            if( $this->min === 'min' ) $this->min = $aYScale->GetMinVal();
     595            if( $this->max === 'max' ) $this->max = $aYScale->GetMaxVal();
    596596
    597597            // Only draw the bar if it actually appears in the range
    598598            if ($this->min < $aYScale->GetMaxVal() && $this->max > $aYScale->GetMinVal()) {
    599                 
    600                 // Trucate to limit of axis
    601                 $this->min = max($this->min, $aYScale->GetMinVal());
    602                 $this->max = min($this->max, $aYScale->GetMaxVal());
    603 
    604                 $x=$aXScale->scale_abs[0];
    605                 $y=$aYScale->Translate($this->max);
    606                 $width=$aXScale->scale_abs[1]-$aXScale->scale_abs[0]+1;
    607                 $height=abs($y-$aYScale->Translate($this->min))+1;
    608                 $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
    609                 $this->prect->Stroke($aImg);
     599           
     600            // Trucate to limit of axis
     601            $this->min = max($this->min, $aYScale->GetMinVal());
     602            $this->max = min($this->max, $aYScale->GetMaxVal());
     603
     604            $x=$aXScale->scale_abs[0];
     605            $y=$aYScale->Translate($this->max);
     606            $width=$aXScale->scale_abs[1]-$aXScale->scale_abs[0]+1;
     607            $height=abs($y-$aYScale->Translate($this->min))+1;
     608            $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
     609            $this->prect->Stroke($aImg);
    610610            }
    611         }
    612         else { // VERTICAL
    613             if( $this->min === 'min' ) $this->min = $aXScale->GetMinVal();
    614             if( $this->max === 'max' ) $this->max = $aXScale->GetMaxVal();
    615 
     611        }
     612        else {  // VERTICAL
     613            if( $this->min === 'min' ) $this->min = $aXScale->GetMinVal();
     614            if( $this->max === 'max' ) $this->max = $aXScale->GetMaxVal();
     615           
    616616            // Only draw the bar if it actually appears in the range
    617             if ($this->min < $aXScale->GetMaxVal() && $this->max > $aXScale->GetMinVal()) {
    618                 
    619                 // Trucate to limit of axis
    620                 $this->min = max($this->min, $aXScale->GetMinVal());
    621                 $this->max = min($this->max, $aXScale->GetMaxVal());
    622 
    623                 $y=$aYScale->scale_abs[1];
    624                 $x=$aXScale->Translate($this->min);
    625                 $height=abs($aYScale->scale_abs[1]-$aYScale->scale_abs[0]);
    626                 $width=abs($x-$aXScale->Translate($this->max));
    627                 $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
    628                 $this->prect->Stroke($aImg);
     617            if ($this->min < $aXScale->GetMaxVal() && $this->max > $aXScale->GetMinVal()) {
     618           
     619            // Trucate to limit of axis
     620            $this->min = max($this->min, $aXScale->GetMinVal());
     621            $this->max = min($this->max, $aXScale->GetMaxVal());
     622
     623            $y=$aYScale->scale_abs[1];
     624            $x=$aXScale->Translate($this->min);
     625            $height=abs($aYScale->scale_abs[1]-$aYScale->scale_abs[0]);
     626            $width=abs($x-$aXScale->Translate($this->max));
     627            $this->prect->SetPos(new Rectangle($x,$y,$width,$height));
     628            $this->prect->Stroke($aImg);
    629629            }
    630         }
     630        }
    631631    }
    632632}
  • trunk/client/modules/Elezioni/grafici/jpgraph_plotmark.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_PLOTMARK.PHP
    4 // Description: Class file. Handles plotmarks
    5 // Created:     2003-03-21
    6 // Ver:         $Id: jpgraph_plotmark.inc.php 1106 2009-02-22 20:16:35Z ljp $
     3// File:        JPGRAPH_PLOTMARK.PHP
     4// Description: Class file. Handles plotmarks
     5// Created:     2003-03-21
     6// Ver:         $Id: jpgraph_plotmark.inc.php 956 2007-11-17 13:19:20Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    3131    private $imgdata_pushpins = null;
    3232
    33     //--------------
    34     // CONSTRUCTOR
    35     function __construct() {
    36         $this->title = new Text();
    37         $this->title->Hide();
    38         $this->csimareas = '';
    39         $this->type=-1;
    40     }
    41     //---------------
    42     // PUBLIC METHODS
     33//--------------
     34// CONSTRUCTOR
     35    function PlotMark() {
     36        $this->title = new Text();
     37        $this->title->Hide();
     38        $this->csimareas = '';
     39        $this->type=-1;
     40    }
     41//---------------
     42// PUBLIC METHODS       
    4343    function SetType($aType,$aFileName='',$aScale=1.0) {
    44         $this->type = $aType;
    45         if( $aType == MARK_IMG && $aFileName=='' ) {
    46             JpGraphError::RaiseL(23003);//('A filename must be specified if you set the mark type to MARK_IMG.');
    47         }
    48         $this->iFileName = $aFileName;
    49         $this->iScale = $aScale;
    50     }
    51 
     44        $this->type = $aType;
     45        if( $aType == MARK_IMG && $aFileName=='' ) {
     46            JpGraphError::RaiseL(23003);//('A filename must be specified if you set the mark type to MARK_IMG.');
     47        }
     48        $this->iFileName = $aFileName;
     49        $this->iScale = $aScale;
     50    }
     51       
    5252    function SetCallback($aFunc) {
    53         $this->iFormatCallback = $aFunc;
     53        $this->iFormatCallback = $aFunc;
    5454    }
    5555
    5656    function SetCallbackYX($aFunc) {
    57         $this->iFormatCallback2 = $aFunc;
    58     }
    59 
     57        $this->iFormatCallback2 = $aFunc;
     58    }
     59   
    6060    function GetType() {
    61         return $this->type;
    62     }
    63 
     61        return $this->type;
     62    }
     63       
    6464    function SetColor($aColor) {
    65         $this->color=$aColor;
    66     }
    67 
     65        $this->color=$aColor;
     66    }
     67       
    6868    function SetFillColor($aFillColor) {
    69         $this->fill_color = $aFillColor;
     69        $this->fill_color = $aFillColor;
    7070    }
    7171
    7272    function SetWeight($aWeight) {
    73         $this->weight = $aWeight;
     73        $this->weight = $aWeight;
    7474    }
    7575
    7676    // Synonym for SetWidth()
    7777    function SetSize($aWidth) {
    78         $this->width=$aWidth;
    79     }
    80 
     78        $this->width=$aWidth;
     79    }
     80       
    8181    function SetWidth($aWidth) {
    82         $this->width=$aWidth;
     82        $this->width=$aWidth;
    8383    }
    8484
    8585    function SetDefaultWidth() {
    86         switch( $this->type ) {
    87             case MARK_CIRCLE:
    88             case MARK_FILLEDCIRCLE:
    89                 $this->width=4;
    90                 break;
    91             default:
    92                 $this->width=7;
    93         }
    94     }
    95 
     86        switch( $this->type ) {
     87            case MARK_CIRCLE:
     88            case MARK_FILLEDCIRCLE:
     89                $this->width=4;
     90                break;
     91            default:
     92                $this->width=7;
     93        }
     94    }
     95       
    9696    function GetWidth() {
    97         return $this->width;
    98     }
    99 
     97        return $this->width;
     98    }
     99       
    100100    function Hide($aHide=true) {
    101         $this->show = !$aHide;
    102     }
    103 
     101        $this->show = !$aHide;
     102    }
     103       
    104104    function Show($aShow=true) {
    105         $this->show = $aShow;
     105        $this->show = $aShow;
    106106    }
    107107
    108108    function SetCSIMAltVal($aY,$aX='') {
    109         $this->yvalue=$aY;
    110         $this->xvalue=$aX;
    111     }
    112 
     109        $this->yvalue=$aY; 
     110        $this->xvalue=$aX; 
     111    }
     112   
    113113    function SetCSIMTarget($aTarget,$aWinTarget='') {
    114114        $this->csimtarget=$aTarget;
    115115        $this->csimwintarget=$aWinTarget;
    116116    }
    117 
     117   
    118118    function SetCSIMAlt($aAlt) {
    119119        $this->csimalt=$aAlt;
    120120    }
    121 
     121   
    122122    function GetCSIMAreas(){
    123123        return $this->csimareas;
    124124    }
    125 
     125       
    126126    function AddCSIMPoly($aPts) {
    127127        $coords = round($aPts[0]).", ".round($aPts[1]);
     
    130130            $coords .= ", ".round($aPts[2*$i]).", ".round($aPts[2*$i+1]);
    131131        }
    132         $this->csimareas="";
     132        $this->csimareas="";   
    133133        if( !empty($this->csimtarget) ) {
    134             $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($this->csimtarget)."\"";
    135 
    136             if( !empty($this->csimwintarget) ) {
    137                 $this->csimareas .= " target=\"".$this->csimwintarget."\" ";
    138             }
    139 
    140             if( !empty($this->csimalt) ) {
    141                 $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
    142                 $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\"";
    143             }
    144             $this->csimareas .= " />\n";
     134            $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($this->csimtarget)."\"";
     135
     136            if( !empty($this->csimwintarget) ) {
     137                $this->csimareas .= " target=\"".$this->csimwintarget."\" ";
     138            }
     139
     140            if( !empty($this->csimalt) ) {                                                                             
     141                $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
     142                $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\"";
     143            }
     144            $this->csimareas .= " />\n";
     145        }
     146    }
     147   
     148    function AddCSIMCircle($x,$y,$r) {
     149        $x = round($x); $y=round($y); $r=round($r);
     150        $this->csimareas="";   
     151        if( !empty($this->csimtarget) ) {
     152            $this->csimareas .= "<area shape=\"circle\" coords=\"$x,$y,$r\" href=\"".htmlentities($this->csimtarget)."\"";
     153
     154            if( !empty($this->csimwintarget) ) {
     155                $this->csimareas .= " target=\"".$this->csimwintarget."\" ";
     156            }
     157
     158            if( !empty($this->csimalt) ) {                                                                             
     159                $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
     160                $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
     161            }
     162            $this->csimareas .= " />\n";
    145163        }
    146164    }
    147 
    148     function AddCSIMCircle($x,$y,$r) {
    149         $x = round($x); $y=round($y); $r=round($r);
    150         $this->csimareas="";
    151         if( !empty($this->csimtarget) ) {
    152             $this->csimareas .= "<area shape=\"circle\" coords=\"$x,$y,$r\" href=\"".htmlentities($this->csimtarget)."\"";
    153 
    154             if( !empty($this->csimwintarget) ) {
    155                 $this->csimareas .= " target=\"".$this->csimwintarget."\" ";
    156             }
    157 
    158             if( !empty($this->csimalt) ) {
    159                 $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
    160                 $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
    161             }
    162             $this->csimareas .= " />\n";
    163         }
    164     }
    165      
     165       
    166166    function Stroke($img,$x,$y) {
    167         if( !$this->show ) return;
    168 
    169         if( $this->iFormatCallback != '' || $this->iFormatCallback2 != '' ) {
    170 
    171             if( $this->iFormatCallback != '' ) {
    172                 $f = $this->iFormatCallback;
    173                 list($width,$color,$fcolor) = call_user_func($f,$this->yvalue);
    174                 $filename = $this->iFileName;
    175                 $imgscale = $this->iScale;
    176             }
    177             else {
    178                 $f = $this->iFormatCallback2;
    179                 list($width,$color,$fcolor,$filename,$imgscale) = call_user_func($f,$this->yvalue,$this->xvalue);
    180                 if( $filename=="" ) $filename = $this->iFileName;
    181                 if( $imgscale=="" ) $imgscale = $this->iScale;
    182             }
    183 
    184             if( $width=="" ) $width = $this->width;
    185             if( $color=="" ) $color = $this->color;
    186             if( $fcolor=="" ) $fcolor = $this->fill_color;
    187 
    188         }
    189         else {
    190             $fcolor = $this->fill_color;
    191             $color = $this->color;
    192             $width = $this->width;
    193             $filename = $this->iFileName;
    194             $imgscale = $this->iScale;
    195         }
    196 
    197         if( $this->type == MARK_IMG ||
    198         ($this->type >= MARK_FLAG1 && $this->type <= MARK_FLAG4 ) ||
    199         $this->type >= MARK_IMG_PUSHPIN ) {
    200 
    201             // Note: For the builtin images we use the "filename" parameter
    202             // to denote the color
    203             $anchor_x = 0.5;
    204             $anchor_y = 0.5;
    205             switch( $this->type ) {
    206                 case MARK_FLAG1:
    207                 case MARK_FLAG2:
    208                 case MARK_FLAG3:
    209                 case MARK_FLAG4:
    210                     $this->markimg = FlagCache::GetFlagImgByName($this->type-MARK_FLAG1+1,$filename);
    211                     break;
    212 
    213                 case MARK_IMG :
    214                     // Load an image and use that as a marker
    215                     // Small optimization, if we have already read an image don't
    216                     // waste time reading it again.
    217                     if( $this->markimg == '' || !($this->oldfilename === $filename) ) {
    218                         $this->markimg = Graph::LoadBkgImage('',$filename);
    219                         $this->oldfilename = $filename ;
    220                     }
    221                     break;
    222 
    223                 case MARK_IMG_PUSHPIN:
    224                 case MARK_IMG_SPUSHPIN:
    225                 case MARK_IMG_LPUSHPIN:
    226                     if( $this->imgdata_pushpins == null ) {
    227                         require_once 'imgdata_pushpins.inc.php';
    228                         $this->imgdata_pushpins = new ImgData_PushPins();
    229                     }
    230                     $this->markimg = $this->imgdata_pushpins->GetImg($this->type,$filename);
    231                     list($anchor_x,$anchor_y) = $this->imgdata_pushpins->GetAnchor();
    232                     break;
    233 
    234                 case MARK_IMG_SQUARE:
    235                     if( $this->imgdata_squares == null ) {
    236                         require_once 'imgdata_squares.inc.php';
    237                         $this->imgdata_squares = new ImgData_Squares();
    238                     }
    239                     $this->markimg = $this->imgdata_squares->GetImg($this->type,$filename);
    240                     list($anchor_x,$anchor_y) = $this->imgdata_squares->GetAnchor();
    241                     break;
    242 
    243                 case MARK_IMG_STAR:
    244                     if( $this->imgdata_stars == null ) {
    245                         require_once 'imgdata_stars.inc.php';
    246                         $this->imgdata_stars = new ImgData_Stars();
    247                     }
    248                     $this->markimg = $this->imgdata_stars->GetImg($this->type,$filename);
    249                     list($anchor_x,$anchor_y) = $this->imgdata_stars->GetAnchor();
    250                     break;
    251 
    252                 case MARK_IMG_BEVEL:
    253                     if( $this->imgdata_bevels == null ) {
    254                         require_once 'imgdata_bevels.inc.php';
    255                         $this->imgdata_bevels = new ImgData_Bevels();
    256                     }
    257                     $this->markimg = $this->imgdata_bevels->GetImg($this->type,$filename);
    258                     list($anchor_x,$anchor_y) = $this->imgdata_bevels->GetAnchor();
    259                     break;
    260 
    261                 case MARK_IMG_DIAMOND:
    262                     if( $this->imgdata_diamonds == null ) {
    263                         require_once 'imgdata_diamonds.inc.php';
    264                         $this->imgdata_diamonds = new ImgData_Diamonds();
    265                     }
    266                     $this->markimg = $this->imgdata_diamonds->GetImg($this->type,$filename);
    267                     list($anchor_x,$anchor_y) = $this->imgdata_diamonds->GetAnchor();
    268                     break;
    269 
    270                 case MARK_IMG_BALL:
    271                 case MARK_IMG_SBALL:
    272                 case MARK_IMG_MBALL:
    273                 case MARK_IMG_LBALL:
    274                     if( $this->imgdata_balls == null ) {
    275                         require_once 'imgdata_balls.inc.php';
    276                         $this->imgdata_balls = new ImgData_Balls();
    277                     }
    278                     $this->markimg = $this->imgdata_balls->GetImg($this->type,$filename);
    279                     list($anchor_x,$anchor_y) = $this->imgdata_balls->GetAnchor();
    280                     break;
    281             }
    282 
    283             $w = $img->GetWidth($this->markimg);
    284             $h = $img->GetHeight($this->markimg);
    285             
    286             $dw = round($imgscale * $w );
    287             $dh = round($imgscale * $h );
    288 
    289             // Do potential rotation
    290             list($x,$y) = $img->Rotate($x,$y);
    291 
    292             $dx = round($x-$dw*$anchor_x);
    293             $dy = round($y-$dh*$anchor_y);
    294             
    295             $this->width = max($dx,$dy);
    296             
    297             $img->Copy($this->markimg,$dx,$dy,0,0,$dw,$dh,$w,$h);
    298             if( !empty($this->csimtarget) ) {
    299                 $this->csimareas = "<area shape=\"rect\" coords=\"".
    300                 $dx.','.$dy.','.round($dx+$dw).','.round($dy+$dh).'" '.
    301       "href=\"".htmlentities($this->csimtarget)."\"";
    302 
    303                 if( !empty($this->csimwintarget) ) {
    304                     $this->csimareas .= " target=\"".$this->csimwintarget."\" ";
    305                 }
    306 
    307                 if( !empty($this->csimalt) ) {
    308                     $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
    309                     $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
    310                 }
    311                 $this->csimareas .= " />\n";
    312             }
    313             
    314             // Stroke title
    315             $this->title->Align("center","top");
    316             $this->title->Stroke($img,$x,$y+round($dh/2));
    317             return;
    318         }
    319 
    320         $weight = $this->weight;
    321         $dx=round($width/2,0);
    322         $dy=round($width/2,0);
    323         $pts=0;
    324 
    325         switch( $this->type ) {
    326             case MARK_SQUARE:
    327                 $c[]=$x-$dx;$c[]=$y-$dy;
    328                 $c[]=$x+$dx;$c[]=$y-$dy;
    329                 $c[]=$x+$dx;$c[]=$y+$dy;
    330                 $c[]=$x-$dx;$c[]=$y+$dy;
    331                 $c[]=$x-$dx;$c[]=$y-$dy;
    332                 $pts=5;
    333                 break;
    334             case MARK_UTRIANGLE:
    335                 ++$dx;++$dy;
    336                 $c[]=$x-$dx;$c[]=$y+0.87*$dy; // tan(60)/2*$dx
    337                 $c[]=$x;$c[]=$y-0.87*$dy;
    338                 $c[]=$x+$dx;$c[]=$y+0.87*$dy;
    339                 $c[]=$x-$dx;$c[]=$y+0.87*$dy; // tan(60)/2*$dx
    340                 $pts=4;
    341                 break;
    342             case MARK_DTRIANGLE:
    343                 ++$dx;++$dy;
    344                 $c[]=$x;$c[]=$y+0.87*$dy; // tan(60)/2*$dx
    345                 $c[]=$x-$dx;$c[]=$y-0.87*$dy;
    346                 $c[]=$x+$dx;$c[]=$y-0.87*$dy;
    347                 $c[]=$x;$c[]=$y+0.87*$dy; // tan(60)/2*$dx
    348                 $pts=4;
    349                 break;
    350             case MARK_DIAMOND:
    351                 $c[]=$x;$c[]=$y+$dy;
    352                 $c[]=$x-$dx;$c[]=$y;
    353                 $c[]=$x;$c[]=$y-$dy;
    354                 $c[]=$x+$dx;$c[]=$y;
    355                 $c[]=$x;$c[]=$y+$dy;
    356                 $pts=5;
    357                 break;
    358             case MARK_LEFTTRIANGLE:
    359                 $c[]=$x;$c[]=$y;
    360                 $c[]=$x;$c[]=$y+2*$dy;
    361                 $c[]=$x+$dx*2;$c[]=$y;
    362                 $c[]=$x;$c[]=$y;
    363                 $pts=4;
    364                 break;
    365             case MARK_RIGHTTRIANGLE:
    366                 $c[]=$x-$dx*2;$c[]=$y;
    367                 $c[]=$x;$c[]=$y+2*$dy;
    368                 $c[]=$x;$c[]=$y;
    369                 $c[]=$x-$dx*2;$c[]=$y;
    370                 $pts=4;
    371                 break;
    372             case MARK_FLASH:
    373                 $dy *= 2;
    374                 $c[]=$x+$dx/2; $c[]=$y-$dy;
    375                 $c[]=$x-$dx+$dx/2; $c[]=$y+$dy*0.7-$dy;
    376                 $c[]=$x+$dx/2; $c[]=$y+$dy*1.3-$dy;
    377                 $c[]=$x-$dx+$dx/2; $c[]=$y+2*$dy-$dy;
    378                 $img->SetLineWeight($weight);
    379                 $img->SetColor($color);
    380                 $img->Polygon($c);
    381                 $img->SetLineWeight(1);
    382                 $this->AddCSIMPoly($c);
    383                 break;
    384         }
    385 
    386         if( $pts>0 ) {
    387             $this->AddCSIMPoly($c);
    388             $img->SetLineWeight($weight);
    389             $img->SetColor($fcolor);
    390             $img->FilledPolygon($c);
    391             $img->SetColor($color);
    392             $img->Polygon($c);
    393             $img->SetLineWeight(1);
    394         }
    395         elseif( $this->type==MARK_CIRCLE ) {
    396             $img->SetColor($color);
    397             $img->Circle($x,$y,$width);
    398             $this->AddCSIMCircle($x,$y,$width);
    399         }
    400         elseif( $this->type==MARK_FILLEDCIRCLE ) {
    401             $img->SetColor($fcolor);
    402             $img->FilledCircle($x,$y,$width);
    403             $img->SetColor($color);
    404             $img->Circle($x,$y,$width);
    405             $this->AddCSIMCircle($x,$y,$width);
    406         }
    407         elseif( $this->type==MARK_CROSS ) {
    408             // Oversize by a pixel to match the X
    409             $img->SetColor($color);
    410             $img->SetLineWeight($weight);
    411             $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
    412             $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
    413             $this->AddCSIMCircle($x,$y,$dx);
    414         }
    415         elseif( $this->type==MARK_X ) {
    416             $img->SetColor($color);
    417             $img->SetLineWeight($weight);
    418             $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
    419             $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy);
    420             $this->AddCSIMCircle($x,$y,$dx+$dy);
    421         }
    422         elseif( $this->type==MARK_STAR ) {
    423             $img->SetColor($color);
    424             $img->SetLineWeight($weight);
    425             $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
    426             $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy);
    427             // Oversize by a pixel to match the X
    428             $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
    429             $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
    430             $this->AddCSIMCircle($x,$y,$dx+$dy);
    431         }
    432 
    433         // Stroke title
    434         $this->title->Align("center","center");
    435         $this->title->Stroke($img,$x,$y);
     167        if( !$this->show ) return;
     168
     169        if( $this->iFormatCallback != '' || $this->iFormatCallback2 != '' ) {
     170
     171            if( $this->iFormatCallback != '' ) {
     172                $f = $this->iFormatCallback;
     173                list($width,$color,$fcolor) = call_user_func($f,$this->yvalue);
     174                $filename = $this->iFileName;
     175                $imgscale = $this->iScale;
     176            }
     177            else {
     178                $f = $this->iFormatCallback2;
     179                list($width,$color,$fcolor,$filename,$imgscale) = call_user_func($f,$this->yvalue,$this->xvalue);
     180                if( $filename=="" ) $filename = $this->iFileName;
     181                if( $imgscale=="" ) $imgscale = $this->iScale;
     182            }
     183
     184            if( $width=="" ) $width = $this->width;
     185            if( $color=="" ) $color = $this->color;
     186            if( $fcolor=="" ) $fcolor = $this->fill_color;
     187
     188        }
     189        else {
     190            $fcolor = $this->fill_color;
     191            $color = $this->color;
     192            $width = $this->width;
     193            $filename = $this->iFileName;
     194            $imgscale = $this->iScale;
     195        }
     196
     197        if( $this->type == MARK_IMG ||
     198            ($this->type >= MARK_FLAG1 && $this->type <= MARK_FLAG4 ) ||
     199            $this->type >= MARK_IMG_PUSHPIN ) {
     200
     201            // Note: For the builtin images we use the "filename" parameter
     202            // to denote the color
     203            $anchor_x = 0.5;
     204            $anchor_y = 0.5;
     205            switch( $this->type ) {
     206                case MARK_FLAG1:
     207                case MARK_FLAG2:
     208                case MARK_FLAG3:
     209                case MARK_FLAG4:
     210                    $this->markimg = FlagCache::GetFlagImgByName($this->type-MARK_FLAG1+1,$filename);
     211                    break;
     212
     213                case MARK_IMG :
     214                    // Load an image and use that as a marker
     215                    // Small optimization, if we have already read an image don't
     216                    // waste time reading it again.
     217                    if( $this->markimg == '' || !($this->oldfilename === $filename) ) {
     218                        $this->markimg = Graph::LoadBkgImage('',$filename);
     219                        $this->oldfilename = $filename ;
     220                    }
     221                    break;
     222
     223                case MARK_IMG_PUSHPIN:
     224                case MARK_IMG_SPUSHPIN:
     225                case MARK_IMG_LPUSHPIN:
     226                    if( $this->imgdata_pushpins == null ) {
     227                        require_once 'imgdata_pushpins.inc.php';
     228                        $this->imgdata_pushpins = new ImgData_PushPins();
     229                    }
     230                    $this->markimg = $this->imgdata_pushpins->GetImg($this->type,$filename);
     231                    list($anchor_x,$anchor_y) = $this->imgdata_pushpins->GetAnchor();
     232                    break;
     233
     234                case MARK_IMG_SQUARE:
     235                    if( $this->imgdata_squares == null ) {
     236                        require_once 'imgdata_squares.inc.php';
     237                        $this->imgdata_squares = new ImgData_Squares();
     238                    }
     239                    $this->markimg = $this->imgdata_squares->GetImg($this->type,$filename);
     240                    list($anchor_x,$anchor_y) = $this->imgdata_squares->GetAnchor();
     241                    break;
     242
     243                case MARK_IMG_STAR:
     244                    if( $this->imgdata_stars == null ) {
     245                        require_once 'imgdata_stars.inc.php';
     246                        $this->imgdata_stars = new ImgData_Stars();
     247                    }
     248                    $this->markimg = $this->imgdata_stars->GetImg($this->type,$filename);
     249                    list($anchor_x,$anchor_y) = $this->imgdata_stars->GetAnchor();
     250                    break;
     251
     252                case MARK_IMG_BEVEL:
     253                    if( $this->imgdata_bevels == null ) {
     254                        require_once 'imgdata_bevels.inc.php';
     255                        $this->imgdata_bevels = new ImgData_Bevels();
     256                    }
     257                    $this->markimg = $this->imgdata_bevels->GetImg($this->type,$filename);
     258                    list($anchor_x,$anchor_y) = $this->imgdata_bevels->GetAnchor();
     259                    break;
     260
     261                case MARK_IMG_DIAMOND:
     262                    if( $this->imgdata_diamonds == null ) {
     263                        require_once 'imgdata_diamonds.inc.php';
     264                        $this->imgdata_diamonds = new ImgData_Diamonds();
     265                    }
     266                    $this->markimg = $this->imgdata_diamonds->GetImg($this->type,$filename);
     267                    list($anchor_x,$anchor_y) = $this->imgdata_diamonds->GetAnchor();
     268                    break;
     269
     270                case MARK_IMG_BALL:                 
     271                case MARK_IMG_SBALL:               
     272                case MARK_IMG_MBALL:               
     273                case MARK_IMG_LBALL:               
     274                    if( $this->imgdata_balls == null ) {
     275                        require_once 'imgdata_balls.inc.php';
     276                        $this->imgdata_balls = new ImgData_Balls();
     277                    }
     278                    $this->markimg = $this->imgdata_balls->GetImg($this->type,$filename);
     279                    list($anchor_x,$anchor_y) = $this->imgdata_balls->GetAnchor();
     280                    break;
     281            }
     282
     283            $w = $img->GetWidth($this->markimg);
     284            $h = $img->GetHeight($this->markimg);
     285           
     286            $dw = round($imgscale * $w );
     287            $dh = round($imgscale * $h );
     288
     289            // Do potential rotation
     290            list($x,$y) = $img->Rotate($x,$y);
     291
     292            $dx = round($x-$dw*$anchor_x);
     293            $dy = round($y-$dh*$anchor_y);
     294           
     295            $this->width = max($dx,$dy);
     296           
     297            $img->Copy($this->markimg,$dx,$dy,0,0,$dw,$dh,$w,$h);
     298            if( !empty($this->csimtarget) ) {
     299                $this->csimareas = "<area shape=\"rect\" coords=\"".
     300                    $dx.','.$dy.','.round($dx+$dw).','.round($dy+$dh).'" '.
     301                    "href=\"".htmlentities($this->csimtarget)."\"";
     302               
     303                if( !empty($this->csimwintarget) ) {
     304                    $this->csimareas .= " target=\"".$this->csimwintarget."\" ";
     305                }
     306
     307                if( !empty($this->csimalt) ) {
     308                    $tmp=sprintf($this->csimalt,$this->yvalue,$this->xvalue);
     309                    $this->csimareas .= " title=\"$tmp\" alt=\"$tmp\" ";
     310                }
     311                $this->csimareas .= " />\n";
     312            }
     313           
     314            // Stroke title
     315            $this->title->Align("center","top");
     316            $this->title->Stroke($img,$x,$y+round($dh/2));                     
     317            return;
     318        }
     319
     320        $weight = $this->weight;
     321        $dx=round($width/2,0);
     322        $dy=round($width/2,0);
     323        $pts=0;         
     324
     325        switch( $this->type ) {
     326            case MARK_SQUARE:
     327                $c[]=$x-$dx;$c[]=$y-$dy;
     328                $c[]=$x+$dx;$c[]=$y-$dy;
     329                $c[]=$x+$dx;$c[]=$y+$dy;
     330                $c[]=$x-$dx;$c[]=$y+$dy;
     331                $c[]=$x-$dx;$c[]=$y-$dy;
     332                $pts=5;
     333                break;
     334            case MARK_UTRIANGLE:
     335                ++$dx;++$dy;
     336                $c[]=$x-$dx;$c[]=$y+0.87*$dy;   // tan(60)/2*$dx
     337                $c[]=$x;$c[]=$y-0.87*$dy;
     338                $c[]=$x+$dx;$c[]=$y+0.87*$dy;
     339                $c[]=$x-$dx;$c[]=$y+0.87*$dy;   // tan(60)/2*$dx
     340                $pts=4;
     341                break;
     342            case MARK_DTRIANGLE:
     343                ++$dx;++$dy;                   
     344                $c[]=$x;$c[]=$y+0.87*$dy;       // tan(60)/2*$dx
     345                $c[]=$x-$dx;$c[]=$y-0.87*$dy;
     346                $c[]=$x+$dx;$c[]=$y-0.87*$dy;
     347                $c[]=$x;$c[]=$y+0.87*$dy;       // tan(60)/2*$dx
     348                $pts=4;
     349                break;                         
     350            case MARK_DIAMOND:
     351                $c[]=$x;$c[]=$y+$dy;
     352                $c[]=$x-$dx;$c[]=$y;
     353                $c[]=$x;$c[]=$y-$dy;
     354                $c[]=$x+$dx;$c[]=$y;
     355                $c[]=$x;$c[]=$y+$dy;
     356                $pts=5;
     357                break; 
     358            case MARK_LEFTTRIANGLE:
     359                $c[]=$x;$c[]=$y;
     360                $c[]=$x;$c[]=$y+2*$dy;
     361                $c[]=$x+$dx*2;$c[]=$y;
     362                $c[]=$x;$c[]=$y;
     363                $pts=4;
     364                break;
     365            case MARK_RIGHTTRIANGLE:
     366                $c[]=$x-$dx*2;$c[]=$y;
     367                $c[]=$x;$c[]=$y+2*$dy;
     368                $c[]=$x;$c[]=$y;
     369                $c[]=$x-$dx*2;$c[]=$y;
     370                $pts=4;
     371                break;
     372            case MARK_FLASH:
     373                $dy *= 2;
     374                $c[]=$x+$dx/2; $c[]=$y-$dy;
     375                $c[]=$x-$dx+$dx/2; $c[]=$y+$dy*0.7-$dy;
     376                $c[]=$x+$dx/2; $c[]=$y+$dy*1.3-$dy;
     377                $c[]=$x-$dx+$dx/2; $c[]=$y+2*$dy-$dy;
     378                $img->SetLineWeight($weight);
     379                $img->SetColor($color);                                 
     380                $img->Polygon($c);
     381                $img->SetLineWeight(1);
     382                $this->AddCSIMPoly($c);
     383                break;
     384        }
     385
     386        if( $pts>0 ) {
     387            $this->AddCSIMPoly($c);
     388            $img->SetLineWeight($weight);
     389            $img->SetColor($fcolor);                                                           
     390            $img->FilledPolygon($c);
     391            $img->SetColor($color);                                     
     392            $img->Polygon($c);
     393            $img->SetLineWeight(1);
     394        }
     395        elseif( $this->type==MARK_CIRCLE ) {
     396            $img->SetColor($color);                                     
     397            $img->Circle($x,$y,$width);
     398            $this->AddCSIMCircle($x,$y,$width);
     399        }
     400        elseif( $this->type==MARK_FILLEDCIRCLE ) {
     401            $img->SetColor($fcolor);           
     402            $img->FilledCircle($x,$y,$width);
     403            $img->SetColor($color);     
     404            $img->Circle($x,$y,$width);
     405            $this->AddCSIMCircle($x,$y,$width);
     406        }
     407        elseif( $this->type==MARK_CROSS ) {
     408            // Oversize by a pixel to match the X
     409            $img->SetColor($color);
     410            $img->SetLineWeight($weight);
     411            $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
     412            $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
     413            $this->AddCSIMCircle($x,$y,$dx);       
     414        }
     415        elseif( $this->type==MARK_X ) {
     416            $img->SetColor($color);
     417            $img->SetLineWeight($weight);
     418            $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
     419            $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy);           
     420            $this->AddCSIMCircle($x,$y,$dx+$dy);                   
     421        }                       
     422        elseif( $this->type==MARK_STAR ) {
     423            $img->SetColor($color);
     424            $img->SetLineWeight($weight);
     425            $img->Line($x+$dx,$y+$dy,$x-$dx,$y-$dy);
     426            $img->Line($x-$dx,$y+$dy,$x+$dx,$y-$dy);
     427            // Oversize by a pixel to match the X                               
     428            $img->Line($x,$y+$dy+1,$x,$y-$dy-1);
     429            $img->Line($x-$dx-1,$y,$x+$dx+1,$y);
     430            $this->AddCSIMCircle($x,$y,$dx+$dy);           
     431        }
     432               
     433        // Stroke title
     434        $this->title->Align("center","center");
     435        $this->title->Stroke($img,$x,$y);                       
    436436    }
    437437} // Class
     
    441441//========================================================================
    442442// CLASS ImgData
    443 // Description: Base class for all image data classes that contains the
     443// Description: Base class for all image data classes that contains the 
    444444// real image data.
    445445//========================================================================
    446446class ImgData {
    447     protected $name = '';  // Each subclass gives a name
    448     protected $an = array();  // Data array names
    449     protected $colors = array(); // Available colors
    450     protected $index  = array(); // Index for colors
    451     protected $maxidx = 0 ;  // Max color index
     447    protected $name = '';               // Each subclass gives a name
     448    protected $an = array();            // Data array names
     449    protected $colors = array();        // Available colors
     450    protected $index  = array();        // Index for colors
     451    protected $maxidx = 0 ;             // Max color index
    452452    protected $anchor_x=0.5, $anchor_y=0.5 ;    // Where is the center of the image
    453    
    454     function __construct() {
    455         // Empty
    456     }
    457    
    458453    // Create a GD image from the data and return a GD handle
    459454    function GetImg($aMark,$aIdx) {
    460         $n = $this->an[$aMark];
    461         if( is_string($aIdx) ) {
    462             if( !in_array($aIdx,$this->colors) ) {
    463                 JpGraphError::RaiseL(23001,$this->name,$aIdx);//('This marker "'.($this->name).'" does not exist in color: '.$aIdx);
    464             }
    465             $idx = $this->index[$aIdx];
    466         }
    467         elseif( !is_integer($aIdx) ||
    468         (is_integer($aIdx) && $aIdx > $this->maxidx ) ) {
    469             JpGraphError::RaiseL(23002,$this->name);//('Mark color index too large for marker "'.($this->name).'"');
    470         }
    471         else
    472         $idx = $aIdx ;
    473         return Image::CreateFromString(base64_decode($this->{$n}[$idx][1]));
    474     }
    475    
     455        $n = $this->an[$aMark];
     456        if( is_string($aIdx) ) {
     457            if( !in_array($aIdx,$this->colors) ) {
     458                JpGraphError::RaiseL(23001,$this->name,$aIdx);//('This marker "'.($this->name).'" does not exist in color: '.$aIdx);
     459            }
     460            $idx = $this->index[$aIdx];
     461        }
     462        elseif( !is_integer($aIdx) ||
     463                (is_integer($aIdx) && $aIdx > $this->maxidx ) ) {
     464            JpGraphError::RaiseL(23002,$this->name);//('Mark color index too large for marker "'.($this->name).'"');
     465        }
     466        else
     467            $idx = $aIdx ;
     468        return Image::CreateFromString(base64_decode($this->{$n}[$idx][1]));   
     469    }
    476470    function GetAnchor() {
    477         return array($this->anchor_x,$this->anchor_y);
     471        return array($this->anchor_x,$this->anchor_y);
    478472    }
    479473}
     
    482476// Keep a global flag cache to reduce memory usage
    483477$_gFlagCache=array(
    484 1 => null,
    485 2 => null,
    486 3 => null,
    487 4 => null,
     478    1 => null,
     479    2 => null,
     480    3 => null,
     481    4 => null,
    488482);
    489483// Only supposed to b called as statics
    490484class FlagCache {
    491    
    492485    static function GetFlagImgByName($aSize,$aName) {
    493         global $_gFlagCache;
    494         require_once('jpgraph_flags.php');
    495         if( $_gFlagCache[$aSize] === null ) {
    496             $_gFlagCache[$aSize] = new FlagImages($aSize);
    497         }
    498         $f = $_gFlagCache[$aSize];
    499         $idx = $f->GetIdxByName($aName,$aFullName);
    500         return $f->GetImgByIdx($idx);
     486        global $_gFlagCache;
     487        require_once('jpgraph_flags.php');
     488        if( $_gFlagCache[$aSize] === null ) {
     489            $_gFlagCache[$aSize] = new FlagImages($aSize);
     490        }
     491        $f = $_gFlagCache[$aSize];
     492        $idx = $f->GetIdxByName($aName,$aFullName);
     493        return $f->GetImgByIdx($idx);
    501494    }
    502495}
  • trunk/client/modules/Elezioni/grafici/jpgraph_polar.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_POLAR.PHP
    4  // Description: Polar plot extension for JpGraph
    5  // Created:     2003-02-02
    6  // Ver:         $Id: jpgraph_polar.php 1796 2009-09-07 09:37:19Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_POLAR.PHP
     4// Description: Polar plot extension for JpGraph
     5// Created:     2003-02-02
     6// Ver:         $Id: jpgraph_polar.php 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212require_once ('jpgraph_plotmark.inc.php');
     
    2525// There were two option. 1: Re-implement everything and get a clean design
    2626// and 2: do some "small" trickery and be able to inherit most of
    27 // the functionlity from the main graph package.
     27// the functionlity from the main graph package. 
    2828// We choose 2: here in order to save some time.
    29 //
     29// 
    3030
    3131//--------------------------------------------------------------------------
     
    3737    public $legendcsimalt='';
    3838    public $legend="";
    39     public $csimtargets=array(); // Array of targets for CSIM
    40     public $csimareas="";   // Resultant CSIM area tags
    41     public $csimalts=null;   // ALT:s for corresponding target
     39    public $csimtargets=array();        // Array of targets for CSIM
     40    public $csimareas="";                       // Resultant CSIM area tags     
     41    public $csimalts=null;                      // ALT:s for corresponding target
    4242    public $scale=null;
    4343    private $numpoints=0;
     
    4646    private $coord=null;
    4747
    48     function __construct($aData) {
    49         $n = count($aData);
    50         if( $n & 1 ) {
    51             JpGraphError::RaiseL(17001);
    52             //('Polar plots must have an even number of data point. Each data point is a tuple (angle,radius).');
    53         }
    54         $this->numpoints = $n/2;
    55         $this->coord = $aData;
    56         $this->mark = new PlotMark();
     48    function PolarPlot($aData) {
     49        $n = count($aData);
     50        if( $n & 1 ) {
     51            JpGraphError::RaiseL(17001);
     52//('Polar plots must have an even number of data point. Each data point is a tuple (angle,radius).');
     53        }
     54        $this->numpoints = $n/2;
     55        $this->coord = $aData;
     56        $this->mark = new PlotMark();
    5757    }
    5858
    5959    function SetWeight($aWeight) {
    60         $this->iLineWeight = $aWeight;
     60        $this->iLineWeight = $aWeight;
    6161    }
    6262
    6363    function SetColor($aColor){
    64         $this->iColor = $aColor;
     64        $this->iColor = $aColor;
    6565    }
    6666
    6767    function SetFillColor($aColor){
    68         $this->iFillColor = $aColor;
     68        $this->iFillColor = $aColor;
    6969    }
    7070
    7171    function Max() {
    72         $m = $this->coord[1];
    73         $i=1;
    74         while( $i < $this->numpoints ) {
    75             $m = max($m,$this->coord[2*$i+1]);
    76             ++$i;
    77         }
    78         return $m;
    79     }
    80     // Set href targets for CSIM
     72        $m = $this->coord[1];
     73        $i=1;
     74        while( $i < $this->numpoints ) {
     75            $m = max($m,$this->coord[2*$i+1]); 
     76            ++$i;
     77        }
     78        return $m;
     79    }
     80    // Set href targets for CSIM       
    8181    function SetCSIMTargets($aTargets,$aAlts=null) {
    82         $this->csimtargets=$aTargets;
    83         $this->csimalts=$aAlts;
    84     }
    85 
     82        $this->csimtargets=$aTargets;
     83        $this->csimalts=$aAlts;         
     84    }
     85       
    8686    // Get all created areas
    8787    function GetCSIMareas() {
    88         return $this->csimareas;
    89     }
    90 
     88        return $this->csimareas;
     89    }   
     90       
    9191    function SetLegend($aLegend,$aCSIM="",$aCSIMAlt="") {
    92         $this->legend = $aLegend;
    93         $this->legendcsimtarget = $aCSIM;
    94         $this->legendcsimalt = $aCSIMAlt;
     92        $this->legend = $aLegend;
     93        $this->legendcsimtarget = $aCSIM;
     94        $this->legendcsimalt = $aCSIMAlt;
    9595    }
    9696
     
    9898
    9999    function Legend($aGraph) {
    100         $color = $this->iColor ;
    101         if( $this->legend != "" ) {
    102             if( $this->iFillColor!='' ) {
    103                 $color = $this->iFillColor;
    104                 $aGraph->legend->Add($this->legend,$color,$this->mark,0,
    105                 $this->legendcsimtarget,$this->legendcsimalt);
    106             }
    107             else {
    108                 $aGraph->legend->Add($this->legend,$color,$this->mark,$this->line_style,
    109                 $this->legendcsimtarget,$this->legendcsimalt);
    110             }
    111         }
     100        $color = $this->iColor ;
     101        if( $this->legend != "" ) {
     102            if( $this->iFillColor!='' ) {
     103                $color = $this->iFillColor;
     104                $aGraph->legend->Add($this->legend,$color,$this->mark,0,
     105                                     $this->legendcsimtarget,$this->legendcsimalt);   
     106            }
     107            else {
     108                $aGraph->legend->Add($this->legend,$color,$this->mark,$this->line_style,
     109                                     $this->legendcsimtarget,$this->legendcsimalt);   
     110            }
     111        }
    112112    }
    113113
    114114    function Stroke($img,$scale) {
    115115
    116         $i=0;
    117         $p=array();
    118         $this->csimareas='';
    119         while($i < $this->numpoints) {
    120             list($x1,$y1) = $scale->PTranslate($this->coord[2*$i],$this->coord[2*$i+1]);
    121             $p[2*$i] = $x1;
    122             $p[2*$i+1] = $y1;
    123 
    124             if( isset($this->csimtargets[$i]) ) {
    125                 $this->mark->SetCSIMTarget($this->csimtargets[$i]);
    126                 $this->mark->SetCSIMAlt($this->csimalts[$i]);
    127                 $this->mark->SetCSIMAltVal($this->coord[2*$i], $this->coord[2*$i+1]);
    128                 $this->mark->Stroke($img,$x1,$y1);
    129                 $this->csimareas .= $this->mark->GetCSIMAreas();
    130             }
    131             else {
    132                 $this->mark->Stroke($img,$x1,$y1);
    133             }
    134 
    135             ++$i;
    136         }
    137 
    138         if( $this->iFillColor != '' ) {
    139             $img->SetColor($this->iFillColor);
    140             $img->FilledPolygon($p);
    141         }
    142         $img->SetLineWeight($this->iLineWeight);
    143         $img->SetColor($this->iColor);
    144         $img->Polygon($p,$this->iFillColor!='');
     116        $i=0;
     117        $p=array();
     118        $this->csimareas='';
     119        while($i < $this->numpoints) {
     120            list($x1,$y1) = $scale->PTranslate($this->coord[2*$i],$this->coord[2*$i+1]);
     121            $p[2*$i] = $x1;
     122            $p[2*$i+1] = $y1;
     123       
     124            if( isset($this->csimtargets[$i]) ) {
     125                $this->mark->SetCSIMTarget($this->csimtargets[$i]);
     126                $this->mark->SetCSIMAlt($this->csimalts[$i]);
     127                $this->mark->SetCSIMAltVal($this->coord[2*$i], $this->coord[2*$i+1]);
     128                $this->mark->Stroke($img,$x1,$y1);
     129                $this->csimareas .= $this->mark->GetCSIMAreas();
     130            }
     131            else
     132                $this->mark->Stroke($img,$x1,$y1);
     133
     134            ++$i;
     135        }
     136
     137        if( $this->iFillColor != '' ) {
     138            $img->SetColor($this->iFillColor);
     139            $img->FilledPolygon($p);
     140        }
     141        $img->SetLineWeight($this->iLineWeight);
     142        $img->SetColor($this->iColor);
     143        $img->Polygon($p,$this->iFillColor!='');
    145144    }
    146145}
     
    160159    private $radius_tick_color='black';
    161160
    162     function __construct($img,$aScale) {
    163         parent::__construct($img,$aScale);
     161    function PolarAxis($img,$aScale) {
     162        parent::Axis($img,$aScale);
    164163    }
    165164
    166165    function ShowAngleDegreeMark($aFlg=true) {
    167         $this->show_angle_mark = $aFlg;
     166        $this->show_angle_mark = $aFlg;
    168167    }
    169168
    170169    function SetAngleStep($aStep) {
    171         $this->angle_step=$aStep;
     170        $this->angle_step=$aStep;
    172171    }
    173172
    174173    function HideTicks($aFlg=true,$aAngleFlg=true) {
    175         parent::HideTicks($aFlg,$aFlg);
    176         $this->show_angle_tick = !$aAngleFlg;
     174        parent::HideTicks($aFlg,$aFlg);
     175        $this->show_angle_tick = !$aAngleFlg;
    177176    }
    178177
    179178    function ShowAngleLabel($aFlg=true) {
    180         $this->show_angle_label = $aFlg;
     179        $this->show_angle_label = $aFlg;
    181180    }
    182181
    183182    function ShowGrid($aMajor=true,$aMinor=false,$aAngle=true) {
    184         $this->show_minor_grid = $aMinor;
    185         $this->show_major_grid = $aMajor;
    186         $this->show_angle_grid = $aAngle ;
     183        $this->show_minor_grid = $aMinor;
     184        $this->show_major_grid = $aMajor;
     185        $this->show_angle_grid = $aAngle ;
    187186    }
    188187
    189188    function SetAngleFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=10) {
    190         $this->angle_fontfam = $aFontFam;
    191         $this->angle_fontstyle = $aFontStyle;
    192         $this->angle_fontsize = $aFontSize;
     189        $this->angle_fontfam = $aFontFam;
     190        $this->angle_fontstyle = $aFontStyle;
     191        $this->angle_fontsize = $aFontSize;
    193192    }
    194193
    195194    function SetColor($aColor,$aRadColor='',$aAngleColor='') {
    196         if( $aAngleColor == '' )
    197         $aAngleColor=$aColor;
    198         parent::SetColor($aColor,$aRadColor);
    199         $this->angle_fontcolor = $aAngleColor;
     195        if( $aAngleColor == '' )
     196            $aAngleColor=$aColor;
     197        parent::SetColor($aColor,$aRadColor);
     198        $this->angle_fontcolor = $aAngleColor;
    200199    }
    201200
    202201    function SetGridColor($aMajorColor,$aMinorColor='',$aAngleColor='') {
    203         if( $aMinorColor == '' )
    204         $aMinorColor = $aMajorColor;
    205         if( $aAngleColor == '' )
    206         $aAngleColor = $aMajorColor;
    207 
    208         $this->gridminor_color = $aMinorColor;
    209         $this->gridmajor_color = $aMajorColor;
    210         $this->angle_color = $aAngleColor;
     202        if( $aMinorColor == '' )
     203            $aMinorColor = $aMajorColor;
     204        if( $aAngleColor == '' )
     205            $aAngleColor = $aMajorColor;
     206
     207        $this->gridminor_color = $aMinorColor;
     208        $this->gridmajor_color = $aMajorColor;
     209        $this->angle_color = $aAngleColor;
    211210    }
    212211
    213212    function SetTickColors($aRadColor,$aAngleColor='') {
    214         $this->radius_tick_color = $aRadColor;
    215         $this->angle_tick_color = $aAngleColor;
    216     }
    217 
     213        $this->radius_tick_color = $aRadColor;
     214        $this->angle_tick_color = $aAngleColor;
     215    }
     216   
    218217    // Private methods
    219218    function StrokeGrid($pos) {
    220         $x = round($this->img->left_margin + $this->img->plotwidth/2);
    221         $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
    222 
    223         // Stroke the minor arcs
    224         $pmin = array();
    225         $p = $this->scale->ticks->ticks_pos;
    226         $n = count($p);
    227         $i = 0;
    228         $this->img->SetColor($this->gridminor_color);
    229         while( $i < $n ) {
    230             $r = $p[$i]-$x+1;
    231             $pmin[]=$r;
    232             if( $this->show_minor_grid ) {
    233                 $this->img->Circle($x,$pos,$r);
    234             }
    235             $i++;
    236         }
    237 
    238         $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ;
    239         while( $r < $limit ) {
    240             $off = $r;
    241             $i=1;
    242             $r = $off + round($p[$i]-$x+1);
    243             while( $r < $limit && $i < $n ) {
    244                 $r = $off+$p[$i]-$x;
    245                 $pmin[]=$r;
    246                 if( $this->show_minor_grid ) {
    247                     $this->img->Circle($x,$pos,$r);
    248                 }
    249                 $i++;
    250             }
    251         }
    252 
    253         // Stroke the major arcs
    254         if( $this->show_major_grid ) {
    255             // First determine how many minor step on
    256             // every major step. We have recorded the minor radius
    257             // in pmin and use these values. This is done in order
    258             // to avoid rounding errors if we were to recalculate the
    259             // different major radius.
    260             $pmaj = $this->scale->ticks->maj_ticks_pos;
    261             $p = $this->scale->ticks->ticks_pos;
    262             if( $this->scale->name == 'lin' ) {
    263                 $step=round(($pmaj[1] - $pmaj[0])/($p[1] - $p[0]));
    264             }
    265             else {
    266                 $step=9;
    267             }
    268             $n = round(count($pmin)/$step);
    269             $i = 0;
    270             $this->img->SetColor($this->gridmajor_color);
    271             $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ;
    272             $off = $r;
    273             $i=0;
    274             $r = $pmin[$i*$step];
    275             while( $r < $limit && $i < $n ) {
    276                 $r = $pmin[$i*$step];
    277                 $this->img->Circle($x,$pos,$r);
    278                 $i++;
    279             }
    280         }
    281 
    282         // Draw angles
    283         if( $this->show_angle_grid ) {
    284             $this->img->SetColor($this->angle_color);
    285             $d = max($this->img->plotheight,$this->img->plotwidth)*1.4 ;
    286             $a = 0;
    287             $p = $this->scale->ticks->ticks_pos;
    288             $start_radius = $p[1]-$x;
    289             while( $a < 360 ) {
    290                 if( $a == 90 || $a == 270 ) {
    291                     // Make sure there are no rounding problem with
    292                     // exactly vertical lines
    293                     $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1,
    294                                      $pos-$start_radius*sin($a/180*M_PI),
    295                                      $x+$start_radius*cos($a/180*M_PI)+1,
    296                                      $pos-$d*sin($a/180*M_PI));
    297 
    298                 }
    299                 else {
    300                     $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1,
    301                                      $pos-$start_radius*sin($a/180*M_PI),
    302                                      $x+$d*cos($a/180*M_PI),
    303                                      $pos-$d*sin($a/180*M_PI));
    304                 }
    305                 $a += $this->angle_step;
    306             }
    307         }
     219        $x = round($this->img->left_margin + $this->img->plotwidth/2);
     220        $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
     221
     222        // Stroke the minor arcs
     223        $pmin = array();
     224        $p = $this->scale->ticks->ticks_pos;
     225        $n = count($p);
     226        $i = 0;
     227        $this->img->SetColor($this->gridminor_color);
     228        while( $i < $n ) {
     229            $r = $p[$i]-$x+1;
     230            $pmin[]=$r;
     231            if( $this->show_minor_grid ) {
     232                $this->img->Circle($x,$pos,$r);
     233            }
     234            $i++;
     235        }
     236       
     237        $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ;
     238        while( $r < $limit ) {
     239            $off = $r;
     240            $i=1;
     241            $r = $off + round($p[$i]-$x+1);
     242            while( $r < $limit && $i < $n ) {
     243                $r = $off+$p[$i]-$x;
     244                $pmin[]=$r;
     245                if( $this->show_minor_grid ) {
     246                    $this->img->Circle($x,$pos,$r);
     247                }
     248                $i++;
     249            }
     250        }
     251
     252        // Stroke the major arcs
     253        if( $this->show_major_grid ) {
     254            // First determine how many minor step on
     255            // every major step. We have recorded the minor radius
     256            // in pmin and use these values. This is done in order
     257            // to avoid rounding errors if we were to recalculate the
     258            // different major radius.
     259            $pmaj = $this->scale->ticks->maj_ticks_pos;
     260            $p = $this->scale->ticks->ticks_pos;
     261            if( $this->scale->name == 'lin' ) {
     262                $step=round(($pmaj[1] - $pmaj[0])/($p[1] - $p[0]));
     263            }
     264            else {
     265                $step=9;
     266            }
     267            $n = round(count($pmin)/$step);
     268            $i = 0;
     269            $this->img->SetColor($this->gridmajor_color);
     270            $limit = max($this->img->plotwidth,$this->img->plotheight)*1.4 ;
     271            $off = $r;
     272            $i=0;
     273            $r = $pmin[$i*$step];
     274            while( $r < $limit && $i < $n ) {
     275                $r = $pmin[$i*$step];
     276                $this->img->Circle($x,$pos,$r);
     277                $i++;
     278            }
     279        }
     280
     281        // Draw angles
     282        if( $this->show_angle_grid ) {
     283            $this->img->SetColor($this->angle_color);
     284            $d = max($this->img->plotheight,$this->img->plotwidth)*1.4 ;
     285            $a = 0;
     286            $p = $this->scale->ticks->ticks_pos;
     287            $start_radius = $p[1]-$x;
     288            while( $a < 360 ) {
     289                if( $a == 90 || $a == 270 ) {
     290                    // Make sure there are no rounding problem with
     291                    // exactly vertical lines
     292                    $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1,
     293                                     $pos-$start_radius*sin($a/180*M_PI),
     294                                     $x+$start_radius*cos($a/180*M_PI)+1,
     295                                     $pos-$d*sin($a/180*M_PI));
     296                   
     297                }
     298                else {
     299                    $this->img->Line($x+$start_radius*cos($a/180*M_PI)+1,
     300                                     $pos-$start_radius*sin($a/180*M_PI),
     301                                     $x+$d*cos($a/180*M_PI),
     302                                     $pos-$d*sin($a/180*M_PI));
     303                }
     304                $a += $this->angle_step;
     305            }
     306        }
    308307    }
    309308
    310309    function StrokeAngleLabels($pos,$type) {
    311310
    312         if( !$this->show_angle_label )
    313             return;
    314 
    315         $x0 = round($this->img->left_margin+$this->img->plotwidth/2)+1;
    316 
    317         $d = max($this->img->plotwidth,$this->img->plotheight)*1.42;
    318         $a = $this->angle_step;
    319         $t = new Text();
    320         $t->SetColor($this->angle_fontcolor);
    321         $t->SetFont($this->angle_fontfam,$this->angle_fontstyle,$this->angle_fontsize);
    322         $xright = $this->img->width - $this->img->right_margin;
    323         $ytop = $this->img->top_margin;
    324         $xleft = $this->img->left_margin;
    325         $ybottom = $this->img->height - $this->img->bottom_margin;
    326         $ha = 'left';
    327         $va = 'center';
    328         $w = $this->img->plotwidth/2;
    329         $h = $this->img->plotheight/2;
    330         $xt = $x0; $yt = $pos;
    331         $margin=5;
    332 
    333         $tl  = $this->angle_tick_len ; // Outer len
    334         $tl2 = $this->angle_tick_len2 ; // Interior len
    335 
    336         $this->img->SetColor($this->angle_tick_color);
    337         $rot90 = $this->img->a == 90 ;
    338 
    339         if( $type == POLAR_360 ) {
    340 
    341             // Corner angles of the four corners
    342             $ca1 = atan($h/$w)/M_PI*180;
    343             $ca2 = 180-$ca1;
    344             $ca3 = $ca1+180;
    345             $ca4 = 360-$ca1;
    346             $end = 360;
    347 
    348             while( $a < $end ) {
    349                 $ca = cos($a/180*M_PI);
    350                 $sa = sin($a/180*M_PI);
    351                 $x = $d*$ca;
    352                 $y = $d*$sa;
    353                 $xt=1000;$yt=1000;
    354                 if( $a <= $ca1 || $a >= $ca4 ) {
    355                     $yt = $pos - $w * $y/$x;
    356                     $xt = $xright + $margin;
    357                     if( $rot90 ) {
    358                         $ha = 'center';
    359                         $va = 'top';
    360                     }
    361                     else {
    362                         $ha = 'left';
    363                         $va = 'center';
    364                     }
    365                     $x1=$xright-$tl2; $x2=$xright+$tl;
    366                     $y1=$y2=$yt;
    367                 }
    368                 elseif( $a > $ca1 && $a < $ca2 ) {
    369                     $xt = $x0 + $h * $x/$y;
    370                     $yt = $ytop - $margin;
    371                     if( $rot90 ) {
    372                         $ha = 'left';
    373                         $va = 'center';
    374                     }
    375                     else {
    376                         $ha = 'center';
    377                         $va = 'bottom';
    378                     }
    379                     $y1=$ytop+$tl2;$y2=$ytop-$tl;
    380                     $x1=$x2=$xt;
    381                 }
    382                 elseif( $a >= $ca2 && $a <= $ca3 ) {
    383                     $yt = $pos + $w * $y/$x;
    384                     $xt = $xleft - $margin;
    385                     if( $rot90 ) {
    386                         $ha = 'center';
    387                         $va = 'bottom';
    388                     }
    389                     else {
    390                         $ha = 'right';
    391                         $va = 'center';
    392                     }
    393                     $x1=$xleft+$tl2;$x2=$xleft-$tl;
    394                     $y1=$y2=$yt;
    395                 }
    396                 else {
    397                     $xt = $x0 - $h * $x/$y;
    398                     $yt = $ybottom + $margin;
    399                     if( $rot90 ) {
    400                         $ha = 'right';
    401                         $va = 'center';
    402                     }
    403                     else {
    404                         $ha = 'center';
    405                         $va = 'top';
    406                     }
    407                     $y1=$ybottom-$tl2;$y2=$ybottom+$tl;
    408                     $x1=$x2=$xt;
    409                 }
    410                 if( $a != 0 && $a != 180 ) {
    411                     $t->Align($ha,$va);
    412                     if( $this->scale->clockwise ) {
    413                         $t->Set(360-$a);
    414                     }
    415                     else {
    416                         $t->Set($a);
    417                     }
    418                     if( $this->show_angle_mark && $t->font_family > 4 ) {
    419                         $a .= SymChar::Get('degree');
    420                     }
    421                     $t->Stroke($this->img,$xt,$yt);
    422                     if( $this->show_angle_tick ) {
    423                         $this->img->Line($x1,$y1,$x2,$y2);
    424                     }
    425                 }
    426                 $a = (int) $a;
    427                 $a += $this->angle_step;
    428             }
    429         }
    430         else {
    431             // POLAR_HALF
    432             $ca1 = atan($h/$w*2)/M_PI*180;
    433             $ca2 = 180-$ca1;
    434             $end = 180;
    435             while( $a < $end ) {
    436                 $ca = cos($a/180*M_PI);
    437                 $sa = sin($a/180*M_PI);
    438                 $x = $d*$ca;
    439                 $y = $d*$sa;
    440                 if( $a <= $ca1 ) {
    441                     $yt = $pos - $w * $y/$x;
    442                     $xt = $xright + $margin;
    443                     if( $rot90 ) {
    444                         $ha = 'center';
    445                         $va = 'top';
    446                     }
    447                     else {
    448                         $ha = 'left';
    449                         $va = 'center';
    450                     }
    451                     $x1=$xright-$tl2; $x2=$xright+$tl;
    452                     $y1=$y2=$yt;
    453                 }
    454                 elseif( $a > $ca1 && $a < $ca2 ) {
    455                     $xt = $x0 + 2*$h * $x/$y;
    456                     $yt = $ytop - $margin;
    457                     if( $rot90 ) {
    458                         $ha = 'left';
    459                         $va = 'center';
    460                     }
    461                     else {
    462                         $ha = 'center';
    463                         $va = 'bottom';
    464                     }
    465                     $y1=$ytop+$tl2;$y2=$ytop-$tl;
    466                     $x1=$x2=$xt;
    467                 }
    468                 elseif( $a >= $ca2 ) {
    469                     $yt = $pos + $w * $y/$x;
    470                     $xt = $xleft - $margin;
    471                     if( $rot90 ) {
    472                         $ha = 'center';
    473                         $va = 'bottom';
    474                     }
    475                     else {
    476                         $ha = 'right';
    477                         $va = 'center';
    478                     }
    479                     $x1=$xleft+$tl2;$x2=$xleft-$tl;
    480                     $y1=$y2=$yt;
    481                 }
    482                 $t->Align($ha,$va);
    483                 if( $this->show_angle_mark && $t->font_family > 4 ) {
    484                         $a .= SymChar::Get('degree');
    485                 }
    486                 $t->Set($a);
    487                 $t->Stroke($this->img,$xt,$yt);
    488                 if( $this->show_angle_tick ) {
    489                     $this->img->Line($x1,$y1,$x2,$y2);
    490                 }
    491                 $a = (int) $a;
    492                 $a += $this->angle_step;
    493             }
    494         }
     311        if( !$this->show_angle_label )
     312            return;
     313       
     314        $x0 = round($this->img->left_margin+$this->img->plotwidth/2)+1;
     315
     316        $d = max($this->img->plotwidth,$this->img->plotheight)*1.42;
     317        $a = $this->angle_step;
     318        $t = new Text();
     319        $t->SetColor($this->angle_fontcolor);
     320        $t->SetFont($this->angle_fontfam,$this->angle_fontstyle,$this->angle_fontsize);
     321        $xright = $this->img->width - $this->img->right_margin;
     322        $ytop = $this->img->top_margin;
     323        $xleft = $this->img->left_margin;
     324        $ybottom = $this->img->height - $this->img->bottom_margin;
     325        $ha = 'left';
     326        $va = 'center';
     327        $w = $this->img->plotwidth/2;
     328        $h = $this->img->plotheight/2;
     329        $xt = $x0; $yt = $pos;
     330        $margin=5;
     331
     332        $tl  = $this->angle_tick_len ; // Outer len
     333        $tl2 = $this->angle_tick_len2 ; // Interior len
     334
     335        $this->img->SetColor($this->angle_tick_color);
     336        $rot90 = $this->img->a == 90 ;
     337
     338        if( $type == POLAR_360 ) {
     339            $ca1 = atan($h/$w)/M_PI*180;
     340            $ca2 = 180-$ca1;
     341            $ca3 = $ca1+180;
     342            $ca4 = 360-$ca1;
     343            $end = 360;
     344            while( $a < $end ) {
     345                $ca = cos($a/180*M_PI);
     346                $sa = sin($a/180*M_PI);
     347                $x = $d*$ca;
     348                $y = $d*$sa;
     349                $xt=1000;$yt=1000;
     350                if( $a <= $ca1 || $a >= $ca4 ) {
     351                    $yt = $pos - $w * $y/$x;
     352                    $xt = $xright + $margin;
     353                    if( $rot90 ) {
     354                        $ha = 'center';
     355                        $va = 'top';
     356                    }
     357                    else {
     358                        $ha = 'left';
     359                        $va = 'center';
     360                    }
     361                    $x1=$xright-$tl2; $x2=$xright+$tl;
     362                    $y1=$y2=$yt;
     363                }
     364                elseif( $a > $ca1 && $a < $ca2 ) {
     365                    $xt = $x0 + $h * $x/$y;
     366                    $yt = $ytop - $margin;
     367                    if( $rot90 ) {
     368                        $ha = 'left';
     369                        $va = 'center';
     370                    }
     371                    else {
     372                        $ha = 'center';
     373                        $va = 'bottom';
     374                    }
     375                    $y1=$ytop+$tl2;$y2=$ytop-$tl;
     376                    $x1=$x2=$xt;
     377                }
     378                elseif( $a >= $ca2 && $a <= $ca3 ) {
     379                    $yt = $pos + $w * $y/$x;
     380                    $xt = $xleft - $margin;
     381                    if( $rot90 ) {
     382                        $ha = 'center';
     383                        $va = 'bottom';
     384                    }
     385                    else {
     386                        $ha = 'right';
     387                        $va = 'center';
     388                    }
     389                    $x1=$xleft+$tl2;$x2=$xleft-$tl;
     390                    $y1=$y2=$yt;
     391                }
     392                else {
     393                    $xt = $x0 - $h * $x/$y;
     394                    $yt = $ybottom + $margin;
     395                    if( $rot90 ) {
     396                        $ha = 'right';
     397                        $va = 'center';
     398                    }
     399                    else {
     400                        $ha = 'center';
     401                        $va = 'top';
     402                    }
     403                    $y1=$ybottom-$tl2;$y2=$ybottom+$tl;
     404                    $x1=$x2=$xt;
     405                }
     406                if( $a != 0 && $a != 180 ) {
     407                    $t->Align($ha,$va);
     408                    if( $this->show_angle_mark )
     409                        $a .= '°';
     410                    $t->Set($a);
     411                    $t->Stroke($this->img,$xt,$yt);   
     412                    if( $this->show_angle_tick )
     413                        $this->img->Line($x1,$y1,$x2,$y2);
     414                }
     415                $a += $this->angle_step;
     416            }
     417        }
     418        else {
     419            // POLAR_HALF
     420            $ca1 = atan($h/$w*2)/M_PI*180;
     421            $ca2 = 180-$ca1;
     422            $end = 180;     
     423            while( $a < $end ) {
     424                $ca = cos($a/180*M_PI);
     425                $sa = sin($a/180*M_PI);
     426                $x = $d*$ca;
     427                $y = $d*$sa;
     428                if( $a <= $ca1 ) {
     429                    $yt = $pos - $w * $y/$x;
     430                    $xt = $xright + $margin;
     431                    if( $rot90 ) {
     432                        $ha = 'center';
     433                        $va = 'top';
     434                    }
     435                    else {
     436                        $ha = 'left';
     437                        $va = 'center';
     438                    }
     439                    $x1=$xright-$tl2; $x2=$xright+$tl;
     440                    $y1=$y2=$yt;
     441                }
     442                elseif( $a > $ca1 && $a < $ca2 ) {
     443                    $xt = $x0 + 2*$h * $x/$y;
     444                    $yt = $ytop - $margin;
     445                    if( $rot90 ) {
     446                        $ha = 'left';
     447                        $va = 'center';
     448                    }
     449                    else {
     450                        $ha = 'center';
     451                        $va = 'bottom';
     452                    }
     453                    $y1=$ytop+$tl2;$y2=$ytop-$tl;
     454                    $x1=$x2=$xt;
     455                }
     456                elseif( $a >= $ca2 ) {
     457                    $yt = $pos + $w * $y/$x;
     458                    $xt = $xleft - $margin;
     459                    if( $rot90 ) {
     460                        $ha = 'center';
     461                        $va = 'bottom';
     462                    }
     463                    else {
     464                        $ha = 'right';
     465                        $va = 'center';
     466                    }
     467                    $x1=$xleft+$tl2;$x2=$xleft-$tl;
     468                    $y1=$y2=$yt;
     469                }
     470                $t->Align($ha,$va);
     471                if( $this->show_angle_mark )
     472                    $a .= '°';
     473                $t->Set($a);
     474                $t->Stroke($this->img,$xt,$yt); 
     475                if( $this->show_angle_tick )
     476                    $this->img->Line($x1,$y1,$x2,$y2); 
     477                $a += $this->angle_step;
     478            }
     479        }
    495480    }
    496481
    497482    function Stroke($pos,$dummy=true) {
    498483
    499         $this->img->SetLineWeight($this->weight);
    500         $this->img->SetColor($this->color);
    501         $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
    502         if( !$this->hide_line ) {
    503             $this->img->FilledRectangle($this->img->left_margin,$pos,
    504                                         $this->img->width-$this->img->right_margin,
    505                                         $pos+$this->weight-1);
    506         }
    507         $y=$pos+$this->img->GetFontHeight()+$this->title_margin+$this->title->margin;
    508         if( $this->title_adjust=="high" ) {
    509             $this->title->SetPos($this->img->width-$this->img->right_margin,$y,"right","top");
    510         }
    511         elseif( $this->title_adjust=="middle" || $this->title_adjust=="center" ) {
    512             $this->title->SetPos(($this->img->width-$this->img->left_margin-$this->img->right_margin)/2+$this->img->left_margin,
    513                                 $y,"center","top");
    514         }
    515         elseif($this->title_adjust=="low") {
    516             $this->title->SetPos($this->img->left_margin,$y,"left","top");
    517         }
    518         else {
    519             JpGraphError::RaiseL(17002,$this->title_adjust);
    520             //('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')');
    521         }
    522 
    523 
    524         if (!$this->hide_labels) {
    525             $this->StrokeLabels($pos,false);
    526         }
    527         $this->img->SetColor($this->radius_tick_color);
    528         $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
    529 
     484        $this->img->SetLineWeight($this->weight);
     485        $this->img->SetColor($this->color);             
     486        $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
     487        if( !$this->hide_line )
     488            $this->img->FilledRectangle($this->img->left_margin,$pos,
     489                     $this->img->width-$this->img->right_margin,$pos+$this->weight-1);
     490        $y=$pos+$this->img->GetFontHeight()+$this->title_margin+$this->title->margin;
     491        if( $this->title_adjust=="high" )
     492            $this->title->SetPos($this->img->width-$this->img->right_margin,$y,"right","top");
     493        elseif( $this->title_adjust=="middle" || $this->title_adjust=="center" )
     494            $this->title->SetPos(($this->img->width-$this->img->left_margin-
     495                               $this->img->right_margin)/2+$this->img->left_margin,
     496                              $y,"center","top");
     497        elseif($this->title_adjust=="low")
     498            $this->title->SetPos($this->img->left_margin,$y,"left","top");
     499        else { 
     500            JpGraphError::RaiseL(17002,$this->title_adjust);
     501//('Unknown alignment specified for X-axis title. ('.$this->title_adjust.')');
     502        }
     503
     504       
     505        if (!$this->hide_labels) {
     506            $this->StrokeLabels($pos,false);
     507        }
     508        $this->img->SetColor($this->radius_tick_color);
     509        $this->scale->ticks->Stroke($this->img,$this->scale,$pos);
     510
     511        //
     512        // Mirror the positions for the left side of the scale
    530513        //
    531         // Mirror the positions for the left side of the scale
    532         //
    533         $mid = 2*($this->img->left_margin+$this->img->plotwidth/2);
    534         $n = count($this->scale->ticks->ticks_pos);
    535         $i=0;
    536         while( $i < $n ) {
    537             $this->scale->ticks->ticks_pos[$i] =
    538             $mid-$this->scale->ticks->ticks_pos[$i] ;
    539             ++$i;
    540         }
    541 
    542         $n = count($this->scale->ticks->maj_ticks_pos);
    543         $i=0;
    544         while( $i < $n ) {
    545             $this->scale->ticks->maj_ticks_pos[$i] =
    546             $mid-$this->scale->ticks->maj_ticks_pos[$i] ;
    547             ++$i;
    548         }
    549 
    550         $n = count($this->scale->ticks->maj_ticklabels_pos);
    551         $i=1;
    552         while( $i < $n ) {
    553             $this->scale->ticks->maj_ticklabels_pos[$i] =
    554             $mid-$this->scale->ticks->maj_ticklabels_pos[$i] ;
    555             ++$i;
    556         }
    557 
    558         // Draw the left side of the scale
    559         $n = count($this->scale->ticks->ticks_pos);
    560         $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMinTickAbsSize();
    561 
    562 
    563         // Minor ticks
    564         if( ! $this->scale->ticks->supress_minor_tickmarks ) {
    565             $i=1;
    566             while( $i < $n/2 ) {
    567                 $x = round($this->scale->ticks->ticks_pos[$i]) ;
    568                 $this->img->Line($x,$pos,$x,$yu);
    569                 ++$i;
    570             }
    571         }
    572 
    573         $n = count($this->scale->ticks->maj_ticks_pos);
    574         $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMajTickAbsSize();
    575 
    576 
    577         // Major ticks
    578         if( ! $this->scale->ticks->supress_tickmarks ) {
    579             $i=1;
    580             while( $i < $n/2 ) {
    581                 $x = round($this->scale->ticks->maj_ticks_pos[$i]) ;
    582                 $this->img->Line($x,$pos,$x,$yu);
    583                 ++$i;
    584             }
    585         }
    586         if (!$this->hide_labels) {
    587             $this->StrokeLabels($pos,false);
    588         }
    589         $this->title->Stroke($this->img);
     514        $mid = 2*($this->img->left_margin+$this->img->plotwidth/2);
     515        $n = count($this->scale->ticks->ticks_pos);
     516        $i=0;
     517        while( $i < $n ) {
     518            $this->scale->ticks->ticks_pos[$i] =
     519                $mid-$this->scale->ticks->ticks_pos[$i] ;
     520            ++$i;
     521        }
     522
     523        $n = count($this->scale->ticks->maj_ticks_pos);
     524        $i=0;
     525        while( $i < $n ) {
     526            $this->scale->ticks->maj_ticks_pos[$i] =
     527                $mid-$this->scale->ticks->maj_ticks_pos[$i] ;
     528            ++$i;
     529        }
     530       
     531        $n = count($this->scale->ticks->maj_ticklabels_pos);
     532        $i=1;
     533        while( $i < $n ) {
     534            $this->scale->ticks->maj_ticklabels_pos[$i] =
     535                $mid-$this->scale->ticks->maj_ticklabels_pos[$i] ;
     536            ++$i;
     537        }
     538
     539        // Draw the left side of the scale
     540        $n = count($this->scale->ticks->ticks_pos);
     541        $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMinTickAbsSize();
     542
     543
     544        // Minor ticks
     545        if( ! $this->scale->ticks->supress_minor_tickmarks ) {
     546            $i=1;
     547            while( $i < $n/2 ) {
     548                $x = round($this->scale->ticks->ticks_pos[$i]) ;
     549                $this->img->Line($x,$pos,$x,$yu);
     550                ++$i;
     551            }
     552        }
     553
     554        $n = count($this->scale->ticks->maj_ticks_pos);
     555        $yu = $pos - $this->scale->ticks->direction*$this->scale->ticks->GetMajTickAbsSize();
     556
     557
     558        // Major ticks
     559        if( ! $this->scale->ticks->supress_tickmarks ) {
     560            $i=1;
     561            while( $i < $n/2 ) {
     562                $x = round($this->scale->ticks->maj_ticks_pos[$i]) ;
     563                $this->img->Line($x,$pos,$x,$yu);
     564                ++$i;
     565            }
     566        }
     567        if (!$this->hide_labels) {
     568            $this->StrokeLabels($pos,false);
     569        }
     570        $this->title->Stroke($this->img);       
    590571    }
    591572}
     
    593574class PolarScale extends LinearScale {
    594575    private $graph;
    595     public $clockwise=false;
    596 
    597     function __construct($aMax,$graph,$aClockwise) {
    598         parent::__construct(0,$aMax,'x');
    599         $this->graph = $graph;
    600         $this->clockwise = $aClockwise;
    601     }
    602 
    603     function SetClockwise($aFlg) {
    604         $this->clockwise = $aFlg;
     576
     577    function PolarScale($aMax=0,$graph) {
     578        parent::LinearScale(0,$aMax,'x');
     579        $this->graph = $graph;
    605580    }
    606581
    607582    function _Translate($v) {
    608         return parent::Translate($v);
     583        return parent::Translate($v);
    609584    }
    610585
    611586    function PTranslate($aAngle,$aRad) {
    612 
    613         $m = $this->scale[1];
    614         $w = $this->graph->img->plotwidth/2;
    615         $aRad = $aRad/$m*$w;
    616 
    617         $a = $aAngle/180 * M_PI;
    618         if( $this->clockwise ) {
    619             $a = 2*M_PI-$a;
    620         }
    621 
    622         $x = cos($a) * $aRad;
    623         $y = sin($a) * $aRad;
    624 
    625         $x += $this->_Translate(0);
    626 
    627         if( $this->graph->iType == POLAR_360 ) {
    628             $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y;
    629         }
    630         else {
    631             $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y;
    632         }
    633         return array($x,$y);
     587       
     588        $m = $this->scale[1];
     589        $w = $this->graph->img->plotwidth/2;
     590        $aRad = $aRad/$m*$w;
     591
     592        $x = cos( $aAngle/180 * M_PI ) * $aRad;
     593        $y = sin( $aAngle/180 * M_PI ) * $aRad;
     594
     595        $x += $this->_Translate(0);
     596
     597        if( $this->graph->iType == POLAR_360 ) {
     598            $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y;
     599        }
     600        else {
     601            $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y;
     602        }
     603        return array($x,$y);
    634604    }
    635605}
     
    637607class PolarLogScale extends LogScale {
    638608    private $graph;
    639     public $clockwise=false;
    640 
    641     function __construct($aMax,$graph,$aClockwise=false) {
    642         parent::__construct(0,$aMax,'x');
    643         $this->graph = $graph;
    644         $this->ticks->SetLabelLogType(LOGLABELS_MAGNITUDE);
    645         $this->clockwise = $aClockwise;
    646 
    647     }
    648 
    649     function SetClockwise($aFlg) {
    650         $this->clockwise = $aFlg;
     609    function PolarLogScale($aMax=1,$graph) {
     610        parent::LogScale(0,$aMax,'x');
     611        $this->graph = $graph;
     612        $this->ticks->SetLabelLogType(LOGLABELS_MAGNITUDE);
     613
    651614    }
    652615
    653616    function PTranslate($aAngle,$aRad) {
    654617
    655         if( $aRad == 0 )
    656         $aRad = 1;
    657         $aRad = log10($aRad);
    658         $m = $this->scale[1];
    659         $w = $this->graph->img->plotwidth/2;
    660         $aRad = $aRad/$m*$w;
    661 
    662         $a = $aAngle/180 * M_PI;
    663         if( $this->clockwise ) {
    664             $a = 2*M_PI-$a;
    665         }
    666 
    667         $x = cos( $a ) * $aRad;
    668         $y = sin( $a ) * $aRad;
    669 
    670         $x += $w+$this->graph->img->left_margin;//$this->_Translate(0);
    671         if( $this->graph->iType == POLAR_360 ) {
    672             $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y;
    673         }
    674         else {
    675             $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y;
    676         }
    677         return array($x,$y);
     618        if( $aRad == 0 )
     619            $aRad = 1;
     620        $aRad = log10($aRad);
     621        $m = $this->scale[1];
     622        $w = $this->graph->img->plotwidth/2;
     623        $aRad = $aRad/$m*$w;
     624
     625        $x = cos( $aAngle/180 * M_PI ) * $aRad;
     626        $y = sin( $aAngle/180 * M_PI ) * $aRad;
     627
     628        $x += $w+$this->graph->img->left_margin;//$this->_Translate(0);
     629        if( $this->graph->iType == POLAR_360 ) {
     630            $y = ($this->graph->img->top_margin + $this->graph->img->plotheight/2) - $y;
     631        }
     632        else {
     633            $y = ($this->graph->img->top_margin + $this->graph->img->plotheight) - $y;
     634        }
     635        return array($x,$y);
    678636    }
    679637}
     
    683641    public $axis;
    684642    public $iType=POLAR_360;
    685     private $iClockwise=false;
    686 
    687     function __construct($aWidth=300,$aHeight=200,$aCachedName="",$aTimeOut=0,$aInline=true) {
    688         parent::__construct($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline) ;
    689         $this->SetDensity(TICKD_DENSE);
    690         $this->SetBox();
    691         $this->SetMarginColor('white');
     643   
     644    function PolarGraph($aWidth=300,$aHeight=200,$aCachedName="",$aTimeOut=0,$aInline=true) {
     645        parent::Graph($aWidth,$aHeight,$aCachedName,$aTimeOut,$aInline) ;
     646        $this->SetDensity(TICKD_DENSE);
     647        $this->SetBox();
     648        $this->SetMarginColor('white');
    692649    }
    693650
    694651    function SetDensity($aDense) {
    695         $this->SetTickDensity(TICKD_NORMAL,$aDense);
    696     }
    697 
    698     function SetClockwise($aFlg) {
    699         $this->scale->SetClockwise($aFlg);
     652        $this->SetTickDensity(TICKD_NORMAL,$aDense);
    700653    }
    701654
    702655    function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) {
    703         $adj = ($this->img->height - $this->img->width)/2;
    704         $this->SetAngle(90);
    705         $lm2 = -$adj + ($lm-$rm+$tm+$bm)/2;
    706         $rm2 = -$adj + (-$lm+$rm+$tm+$bm)/2;
    707         $tm2 = $adj + ($tm-$bm+$lm+$rm)/2;
    708         $bm2 = $adj + (-$tm+$bm+$lm+$rm)/2;
    709         $this->SetMargin($lm2, $rm2, $tm2, $bm2);
    710         $this->axis->SetLabelAlign('right','center');
     656        $adj = ($this->img->height - $this->img->width)/2;
     657        $this->SetAngle(90);
     658        $this->img->SetMargin($lm-$adj,$rm-$adj,$tm+$adj,$bm+$adj);
     659        $this->img->SetCenter(floor($this->img->width/2),floor($this->img->height/2));
     660        $this->axis->SetLabelAlign('right','center');
     661        //JpGraphError::Raise('Set90AndMargin() is not supported for polar graphs.');
    711662    }
    712663
    713664    function SetScale($aScale,$rmax=0,$dummy1=1,$dummy2=1,$dummy3=1) {
    714         if( $aScale == 'lin' ) {
    715             $this->scale = new PolarScale($rmax,$this,$this->iClockwise);
    716         }
    717         elseif( $aScale == 'log' ) {
    718             $this->scale = new PolarLogScale($rmax,$this,$this->iClockwise);
    719         }
    720         else {
    721             JpGraphError::RaiseL(17004);//('Unknown scale type for polar graph. Must be "lin" or "log"');
    722         }
    723 
    724         $this->axis = new PolarAxis($this->img,$this->scale);
    725         $this->SetMargin(40,40,50,40);
     665        if( $aScale == 'lin' )
     666            $this->scale = new PolarScale($rmax,$this);
     667        elseif( $aScale == 'log' ) {
     668            $this->scale = new PolarLogScale($rmax,$this);
     669        }
     670        else {
     671            JpGraphError::RaiseL(17004);//('Unknown scale type for polar graph. Must be "lin" or "log"');
     672        }
     673
     674        $this->axis = new PolarAxis($this->img,$this->scale);
     675        $this->SetMargin(40,40,50,40);
    726676    }
    727677
    728678    function SetType($aType) {
    729         $this->iType = $aType;
     679        $this->iType = $aType;
    730680    }
    731681
    732682    function SetPlotSize($w,$h) {
    733         $this->SetMargin(($this->img->width-$w)/2,($this->img->width-$w)/2,
    734                         ($this->img->height-$h)/2,($this->img->height-$h)/2);
     683        $this->SetMargin(($this->img->width-$w)/2,($this->img->width-$w)/2,
     684                        ($this->img->height-$h)/2,($this->img->height-$h)/2);
    735685    }
    736686
    737687    // Private methods
    738688    function GetPlotsMax() {
    739         $n = count($this->plots);
    740         $m = $this->plots[0]->Max();
    741         $i=1;
    742         while($i < $n) {
    743             $m = max($this->plots[$i]->Max(),$m);
    744             ++$i;
    745         }
    746         return $m;
     689        $n = count($this->plots);
     690        $m = $this->plots[0]->Max();
     691        $i=1;
     692        while($i < $n) {
     693            $m = max($this->plots[$i]->Max(),$m);
     694            ++$i;
     695        }
     696        return $m;
    747697    }
    748698
    749699    function Stroke($aStrokeFileName="") {
    750700
    751         // Start by adjusting the margin so that potential titles will fit.
    752         $this->AdjustMarginsForTitles();
    753 
    754         // If the filename is the predefined value = '_csim_special_'
    755         // we assume that the call to stroke only needs to do enough
    756         // to correctly generate the CSIM maps.
    757         // We use this variable to skip things we don't strictly need
    758         // to do to generate the image map to improve performance
    759         // a best we can. Therefor you will see a lot of tests !$_csim in the
    760         // code below.
    761         $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
    762 
    763         // We need to know if we have stroked the plot in the
    764         // GetCSIMareas. Otherwise the CSIM hasn't been generated
    765         // and in the case of GetCSIM called before stroke to generate
    766         // CSIM without storing an image to disk GetCSIM must call Stroke.
    767         $this->iHasStroked = true;
    768 
    769         //Check if we should autoscale axis
    770         if( !$this->scale->IsSpecified() && count($this->plots)>0 ) {
    771             $max = $this->GetPlotsMax();
    772             $t1 = $this->img->plotwidth;
    773             $this->img->plotwidth /= 2;
    774             $t2 = $this->img->left_margin;
    775             $this->img->left_margin += $this->img->plotwidth+1;
    776             $this->scale->AutoScale($this->img,0,$max,
    777             $this->img->plotwidth/$this->xtick_factor/2);
    778             $this->img->plotwidth = $t1;
    779             $this->img->left_margin = $t2;
    780         }
    781         else {
    782             // The tick calculation will use the user suplied min/max values to determine
    783             // the ticks. If auto_ticks is false the exact user specifed min and max
    784             // values will be used for the scale.
    785             // If auto_ticks is true then the scale might be slightly adjusted
    786             // so that the min and max values falls on an even major step.
    787             //$min = 0;
    788             $max = $this->scale->scale[1];
    789             $t1 = $this->img->plotwidth;
    790             $this->img->plotwidth /= 2;
    791             $t2 = $this->img->left_margin;
    792             $this->img->left_margin += $this->img->plotwidth+1;
    793             $this->scale->AutoScale($this->img,0,$max,
    794             $this->img->plotwidth/$this->xtick_factor/2);
    795             $this->img->plotwidth = $t1;
    796             $this->img->left_margin = $t2;
    797         }
    798 
    799         if( $this->iType ==  POLAR_180 ) {
    800                 $pos = $this->img->height - $this->img->bottom_margin;
    801         }
    802         else {
    803                 $pos = $this->img->plotheight/2 + $this->img->top_margin;
    804         }
    805 
    806         if( !$_csim ) {
    807             $this->StrokePlotArea();
    808         }
    809 
    810         $this->iDoClipping = true;
    811 
    812         if( $this->iDoClipping ) {
    813             $oldimage = $this->img->CloneCanvasH();
    814         }
    815 
    816         if( !$_csim ) {
    817             $this->axis->StrokeGrid($pos);
    818         }
    819 
    820         // Stroke all plots for Y1 axis
    821         for($i=0; $i < count($this->plots); ++$i) {
    822             $this->plots[$i]->Stroke($this->img,$this->scale);
    823         }
    824 
    825 
    826         if( $this->iDoClipping ) {
    827             // Clipping only supports graphs at 0 and 90 degrees
    828             if( $this->img->a == 0  ) {
    829                 $this->img->CopyCanvasH($oldimage,$this->img->img,
    830                                         $this->img->left_margin,$this->img->top_margin,
    831                                         $this->img->left_margin,$this->img->top_margin,
    832                                         $this->img->plotwidth+1,$this->img->plotheight+1);
    833             }
    834             elseif( $this->img->a == 90 ) {
    835                 $adj1 = round(($this->img->height - $this->img->width)/2);
    836                 $adj2 = round(($this->img->width - $this->img->height)/2);
    837                 $lm = $this->img->left_margin;
    838                 $rm = $this->img->right_margin;
    839                 $tm = $this->img->top_margin;
    840                 $bm = $this->img->bottom_margin;
    841                 $this->img->CopyCanvasH($oldimage,$this->img->img,
    842                                         $adj2 + round(($lm-$rm+$tm+$bm)/2),
    843                                         $adj1 + round(($tm-$bm+$lm+$rm)/2),
    844                                         $adj2 + round(($lm-$rm+$tm+$bm)/2),
    845                                         $adj1 + round(($tm-$bm+$lm+$rm)/2),
    846                                         $this->img->plotheight+1,
    847                                         $this->img->plotwidth+1);
    848             }
    849             $this->img->Destroy();
    850             $this->img->SetCanvasH($oldimage);
    851         }
    852 
    853         if( !$_csim ) {
    854             $this->axis->Stroke($pos);
    855             $this->axis->StrokeAngleLabels($pos,$this->iType);
    856         }
    857 
    858         if( !$_csim ) {
    859             $this->StrokePlotBox();
    860             $this->footer->Stroke($this->img);
    861 
    862             // The titles and legends never gets rotated so make sure
    863             // that the angle is 0 before stroking them
    864             $aa = $this->img->SetAngle(0);
    865             $this->StrokeTitles();
    866         }
    867 
    868         for($i=0; $i < count($this->plots) ; ++$i ) {
    869             $this->plots[$i]->Legend($this);
    870         }
    871 
    872         $this->legend->Stroke($this->img);
    873 
    874         if( !$_csim ) {
    875 
    876             $this->StrokeTexts();
    877             $this->img->SetAngle($aa);
    878 
    879             // Draw an outline around the image map
    880             if(_JPG_DEBUG)
    881                 $this->DisplayClientSideaImageMapAreas();
    882 
    883             // If the filename is given as the special "__handle"
    884             // then the image handler is returned and the image is NOT
    885             // streamed back
    886             if( $aStrokeFileName == _IMG_HANDLER ) {
    887                 return $this->img->img;
    888             }
    889             else {
    890                 // Finally stream the generated picture
    891                 $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
    892             }
    893         }
     701        // Start by adjusting the margin so that potential titles will fit.
     702        $this->AdjustMarginsForTitles();
     703           
     704        // If the filename is the predefined value = '_csim_special_'
     705        // we assume that the call to stroke only needs to do enough
     706        // to correctly generate the CSIM maps.
     707        // We use this variable to skip things we don't strictly need
     708        // to do to generate the image map to improve performance
     709        // a best we can. Therefor you will see a lot of tests !$_csim in the
     710        // code below.
     711        $_csim = ($aStrokeFileName===_CSIM_SPECIALFILE);
     712
     713        // We need to know if we have stroked the plot in the
     714        // GetCSIMareas. Otherwise the CSIM hasn't been generated
     715        // and in the case of GetCSIM called before stroke to generate
     716        // CSIM without storing an image to disk GetCSIM must call Stroke.
     717        $this->iHasStroked = true;
     718
     719        //Check if we should autoscale axis
     720        if( !$this->scale->IsSpecified() && count($this->plots)>0 ) {
     721            $max = $this->GetPlotsMax();
     722            $t1 = $this->img->plotwidth;
     723            $this->img->plotwidth /= 2;
     724            $t2 = $this->img->left_margin;
     725            $this->img->left_margin += $this->img->plotwidth+1;
     726            $this->scale->AutoScale($this->img,0,$max,
     727                                     $this->img->plotwidth/$this->xtick_factor/2);
     728            $this->img->plotwidth = $t1;
     729            $this->img->left_margin = $t2;
     730        }
     731        else {
     732            // The tick calculation will use the user suplied min/max values to determine
     733            // the ticks. If auto_ticks is false the exact user specifed min and max
     734            // values will be used for the scale.
     735            // If auto_ticks is true then the scale might be slightly adjusted
     736            // so that the min and max values falls on an even major step.
     737            //$min = 0;
     738            $max = $this->scale->scale[1];
     739            $t1 = $this->img->plotwidth;
     740            $this->img->plotwidth /= 2;
     741            $t2 = $this->img->left_margin;
     742            $this->img->left_margin += $this->img->plotwidth+1;
     743            $this->scale->AutoScale($this->img,0,$max,
     744                                     $this->img->plotwidth/$this->xtick_factor/2);
     745            $this->img->plotwidth = $t1;
     746            $this->img->left_margin = $t2;
     747        }
     748
     749        if( $this->iType ==  POLAR_180 )
     750            $pos = $this->img->height - $this->img->bottom_margin;
     751        else
     752            $pos = $this->img->plotheight/2 + $this->img->top_margin;
     753
     754
     755        if( !$_csim ) {
     756            $this->StrokePlotArea();
     757        }
     758
     759        $this->iDoClipping = true;
     760
     761        if( $this->iDoClipping ) {
     762            $oldimage = $this->img->CloneCanvasH();
     763        }
     764
     765        if( !$_csim ) {
     766            $this->axis->StrokeGrid($pos);
     767        }
     768
     769        // Stroke all plots for Y1 axis
     770        for($i=0; $i < count($this->plots); ++$i) {
     771            $this->plots[$i]->Stroke($this->img,$this->scale);
     772        }                                               
     773
     774
     775        if( $this->iDoClipping ) {
     776            // Clipping only supports graphs at 0 and 90 degrees
     777            if( $this->img->a == 0  ) {
     778                $this->img->CopyCanvasH($oldimage,$this->img->img,
     779                                        $this->img->left_margin,$this->img->top_margin,
     780                                        $this->img->left_margin,$this->img->top_margin,
     781                                        $this->img->plotwidth+1,$this->img->plotheight+1);
     782            }
     783            elseif( $this->img->a == 90 ) {
     784                $adj = round(($this->img->height - $this->img->width)/2);
     785                $this->img->CopyCanvasH($oldimage,$this->img->img,
     786                                        $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
     787                                        $this->img->bottom_margin-$adj,$this->img->left_margin+$adj,
     788                                        $this->img->plotheight,$this->img->plotwidth);
     789            }
     790            $this->img->Destroy();
     791            $this->img->SetCanvasH($oldimage);
     792        }
     793
     794        if( !$_csim ) {
     795            $this->axis->Stroke($pos);
     796            $this->axis->StrokeAngleLabels($pos,$this->iType);
     797        }
     798
     799        if( !$_csim ) {
     800            $this->StrokePlotBox();
     801            $this->footer->Stroke($this->img);
     802
     803            // The titles and legends never gets rotated so make sure
     804            // that the angle is 0 before stroking them                         
     805            $aa = $this->img->SetAngle(0);
     806            $this->StrokeTitles();
     807        }
     808
     809        for($i=0; $i < count($this->plots) ; ++$i ) {
     810            $this->plots[$i]->Legend($this);
     811        }
     812
     813        $this->legend->Stroke($this->img);             
     814
     815        if( !$_csim ) {
     816
     817            $this->StrokeTexts();       
     818            $this->img->SetAngle($aa); 
     819                       
     820            // Draw an outline around the image map     
     821            if(_JPG_DEBUG)
     822                $this->DisplayClientSideaImageMapAreas();               
     823           
     824            // If the filename is given as the special "__handle"
     825            // then the image handler is returned and the image is NOT
     826            // streamed back
     827            if( $aStrokeFileName == _IMG_HANDLER ) {
     828                return $this->img->img;
     829            }
     830            else {
     831                // Finally stream the generated picture                                 
     832                $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
     833                                           $aStrokeFileName);           
     834            }
     835        }
    894836    }
    895837}
  • trunk/client/modules/Elezioni/grafici/jpgraph_radar.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_RADAR.PHP
    4  // Description: Radar plot extension for JpGraph
    5  // Created:     2001-02-04
    6  // Ver:         $Id: jpgraph_radar.php 1783 2009-08-25 11:41:01Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_RADAR.PHP
     4// Description: Radar plot extension for JpGraph
     5// Created:     2001-02-04
     6// Ver:         $Id: jpgraph_radar.php 1044 2008-07-31 18:34:55Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212require_once('jpgraph_plotmark.inc.php');
    1313
    14 //===================================================
    15 // CLASS RadarLogTicks
    16 // Description: Logarithmic ticks
    17 //===================================================
    1814class RadarLogTicks extends Ticks {
    19 
    20     function __construct() {
    21             // Empty
    22     }
    23 
     15//---------------
     16// CONSTRUCTOR
     17    function RadarLogTicks() {
     18    }
     19//---------------
     20// PUBLIC METHODS       
     21
     22    // TODO: Add Argument grid
    2423    function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) {
    25         $start = $aScale->GetMinVal();
    26         $limit = $aScale->GetMaxVal();
    27         $nextMajor = 10*$start;
    28         $step = $nextMajor / 10.0;
    29         $count=1;
    30 
    31         $ticklen_maj=5;
    32         $dx_maj=round(sin($aAxisAngle)*$ticklen_maj);
    33         $dy_maj=round(cos($aAxisAngle)*$ticklen_maj);
    34         $ticklen_min=3;
    35         $dx_min=round(sin($aAxisAngle)*$ticklen_min);
    36         $dy_min=round(cos($aAxisAngle)*$ticklen_min);
    37 
    38         $aMajPos=array();
    39         $aMajLabel=array();
    40 
    41         if( $this->supress_first ) {
    42             $aMajLabel[] = '';
    43         }
    44         else {
    45             $aMajLabel[]=$start;
    46         }
    47 
    48         $yr=$aScale->RelTranslate($start);
    49         $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0];
    50         $yt=$aPos-round($yr*sin($aAxisAngle));
    51         $aMajPos[]=$xt+2*$dx_maj;
    52         $aMajPos[]=$yt-$aImg->GetFontheight()/2;
    53         $grid[]=$xt;
    54         $grid[]=$yt;
    55 
    56         $aImg->SetLineWeight($this->weight);
    57 
    58         for($y=$start; $y<=$limit; $y+=$step,++$count  ) {
    59             $yr=$aScale->RelTranslate($y);
    60             $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0];
    61             $yt=$aPos-round($yr*sin($aAxisAngle));
    62             if( $count % 10 == 0 ) {
    63                 $grid[]=$xt;
    64                 $grid[]=$yt;
    65                 $aMajPos[]=$xt+2*$dx_maj;
    66                 $aMajPos[]=$yt-$aImg->GetFontheight()/2;
    67                 if( !$this->supress_tickmarks ) {
    68                     if( $this->majcolor != '' ) {
    69                         $aImg->PushColor($this->majcolor);
    70                     }
    71                     $aImg->Line($xt+$dx_maj,$yt+$dy_maj,$xt-$dx_maj,$yt-$dy_maj);
    72                     if( $this->majcolor != '' ) {
    73                         $aImg->PopColor();
    74                     }
    75                 }
    76                 if( $this->label_formfunc != '' ) {
    77                     $f=$this->label_formfunc;
    78                     $l = call_user_func($f,$nextMajor);
    79                 }
    80                 else {
    81                     $l = $nextMajor;
    82                 }
    83 
    84                 $aMajLabel[]=$l;
    85                 $nextMajor *= 10;
    86                 $step *= 10;
    87                 $count=1;
    88             }
    89             else {
    90                 if( !$this->supress_minor_tickmarks ) {
    91                     if( $this->mincolor != '' ) {
    92                         $aImg->PushColor($this->mincolor);
    93                     }
    94                     $aImg->Line($xt+$dx_min,$yt+$dy_min,$xt-$dx_min,$yt-$dy_min);
    95                     if( $this->mincolor != '' ) {
    96                         $aImg->PopColor();
    97                     }
    98                 }
    99             }
    100         }
    101     }
     24        $start = $aScale->GetMinVal();
     25        $limit = $aScale->GetMaxVal();
     26        $nextMajor = 10*$start;
     27        $step = $nextMajor / 10.0;
     28        $count=1;
     29                               
     30        $ticklen_maj=5;
     31        $dx_maj=round(sin($aAxisAngle)*$ticklen_maj);
     32        $dy_maj=round(cos($aAxisAngle)*$ticklen_maj);
     33        $ticklen_min=3;
     34        $dx_min=round(sin($aAxisAngle)*$ticklen_min);
     35        $dy_min=round(cos($aAxisAngle)*$ticklen_min);
     36                       
     37        $aMajPos=array();
     38        $aMajLabel=array();
     39                       
     40        if( $this->supress_first )
     41            $aMajLabel[]="";
     42        else
     43            $aMajLabel[]=$start;       
     44        $yr=$aScale->RelTranslate($start);     
     45        $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0];
     46        $yt=$aPos-round($yr*sin($aAxisAngle));
     47        $aMajPos[]=$xt+2*$dx_maj;
     48        $aMajPos[]=$yt-$aImg->GetFontheight()/2;
     49        $grid[]=$xt;
     50        $grid[]=$yt;
     51
     52        $aImg->SetLineWeight($this->weight);                   
     53               
     54        for($y=$start; $y<=$limit; $y+=$step,++$count  ) {
     55            $yr=$aScale->RelTranslate($y);     
     56            $xt=round($yr*cos($aAxisAngle))+$aScale->scale_abs[0];
     57            $yt=$aPos-round($yr*sin($aAxisAngle));
     58            if( $count % 10 == 0 ) {
     59                $grid[]=$xt;
     60                $grid[]=$yt;
     61                $aMajPos[]=$xt+2*$dx_maj;
     62                $aMajPos[]=$yt-$aImg->GetFontheight()/2;                                                       
     63                if( !$this->supress_tickmarks ) {               
     64                    if( $this->majcolor!="" ) $aImg->PushColor($this->majcolor);
     65                    $aImg->Line($xt+$dx_maj,$yt+$dy_maj,$xt-$dx_maj,$yt-$dy_maj);
     66                    if( $this->majcolor!="" ) $aImg->PopColor();
     67                }
     68                if( $this->label_formfunc != "" ) {
     69                    $f=$this->label_formfunc;
     70                    $l = call_user_func($f,$nextMajor);
     71                }
     72                else
     73                    $l = $nextMajor;
     74
     75                $aMajLabel[]=$l;       
     76                $nextMajor *= 10;
     77                $step *= 10;   
     78                $count=1;                               
     79            }
     80            else
     81                if( !$this->supress_minor_tickmarks )   {
     82                    if( $this->mincolor!="" ) $aImg->PushColor($this->mincolor);
     83                    $aImg->Line($xt+$dx_min,$yt+$dy_min,$xt-$dx_min,$yt-$dy_min);
     84                    if( $this->mincolor!="" ) $aImg->PopColor();
     85                }
     86        }               
     87    }           
    10288}
    103 
    104 //===================================================
    105 // CLASS RadarLinear
    106 // Description: Linear ticks
    107 //===================================================
    108 class RadarLinearTicks extends Ticks {
     89       
     90class RadarLinearTicks extends Ticks {
    10991
    11092    private $minor_step=1, $major_step=2;
    11193    private $xlabel_offset=0,$xtick_offset=0;
    11294
    113     function __construct() {
    114         // Empty
    115     }
    116 
     95//---------------
     96// CONSTRUCTOR
     97    function RadarLinearTicks() {
     98        // Empty
     99    }
     100
     101//---------------
     102// PUBLIC METHODS       
     103
     104       
    117105    // Return major step size in world coordinates
    118106    function GetMajor() {
    119         return $this->major_step;
    120     }
    121 
     107        return $this->major_step;
     108    }
     109       
    122110    // Return minor step size in world coordinates
    123111    function GetMinor() {
    124         return $this->minor_step;
    125     }
    126 
     112        return $this->minor_step;
     113    }
     114       
    127115    // Set Minor and Major ticks (in world coordinates)
    128116    function Set($aMajStep,$aMinStep=false) {
    129         if( $aMinStep==false ) {
    130             $aMinStep=$aMajStep;
    131         }
    132 
    133         if( $aMajStep <= 0 || $aMinStep <= 0 ) {
    134             JpGraphError::RaiseL(25064);
    135             //JpGraphError::Raise(" Minor or major step size is 0. Check that you haven't got an accidental SetTextTicks(0) in your code. If this is not the case you might have stumbled upon a bug in JpGraph. Please report this and if possible include the data that caused the problem.");
    136         }
    137 
    138         $this->major_step=$aMajStep;
    139         $this->minor_step=$aMinStep;
    140         $this->is_set = true;
     117        if( $aMinStep==false )
     118            $aMinStep=$aMajStep;
     119       
     120        if( $aMajStep <= 0 || $aMinStep <= 0 ) {
     121            JpGraphError::Raise(" Minor or major step size is 0. Check that you haven't
     122                                got an accidental SetTextTicks(0) in your code.<p>
     123                                If this is not the case you might have stumbled upon a bug in JpGraph.
     124                                Please report this and if possible include the data that caused the
     125                                problem.");
     126        }
     127               
     128        $this->major_step=$aMajStep;
     129        $this->minor_step=$aMinStep;
     130        $this->is_set = true;
    141131    }
    142132
    143133    function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) {
    144         // Prepare to draw linear ticks
    145         $maj_step_abs = abs($aScale->scale_factor*$this->major_step);
    146         $min_step_abs = abs($aScale->scale_factor*$this->minor_step);
    147         $nbrmaj = round($aScale->world_abs_size/$maj_step_abs);
    148         $nbrmin = round($aScale->world_abs_size/$min_step_abs);
    149         $skip = round($nbrmin/$nbrmaj); // Don't draw minor on top of major
    150 
    151         // Draw major ticks
    152         $ticklen2=$this->major_abs_size;
    153         $dx=round(sin($aAxisAngle)*$ticklen2);
    154         $dy=round(cos($aAxisAngle)*$ticklen2);
    155         $label=$aScale->scale[0]+$this->major_step;
    156 
    157         $aImg->SetLineWeight($this->weight);
    158 
    159         $aMajPos = array();
    160         $aMajLabel = array();
    161 
    162         for($i=1; $i<=$nbrmaj; ++$i) {
    163             $xt=round($i*$maj_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0];
    164             $yt=$aPos-round($i*$maj_step_abs*sin($aAxisAngle));
    165 
    166             if( $this->label_formfunc != '' ) {
    167                 $f=$this->label_formfunc;
    168                 $l = call_user_func($f,$label);
    169             }
    170             else {
    171                 $l = $label;
    172             }
    173 
    174             $aMajLabel[]=$l;
    175             $label += $this->major_step;
    176             $grid[]=$xt;
    177             $grid[]=$yt;
    178             $aMajPos[($i-1)*2]=$xt+2*$dx;
    179             $aMajPos[($i-1)*2+1]=$yt-$aImg->GetFontheight()/2;
    180             if( !$this->supress_tickmarks ) {
    181                 if( $this->majcolor != '' ) {
    182                     $aImg->PushColor($this->majcolor);
    183                 }
    184                 $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy);
    185                 if( $this->majcolor != '' ) {
    186                     $aImg->PopColor();
    187                 }
    188             }
    189         }
    190 
    191         // Draw minor ticks
    192         $ticklen2=$this->minor_abs_size;
    193         $dx=round(sin($aAxisAngle)*$ticklen2);
    194         $dy=round(cos($aAxisAngle)*$ticklen2);
    195         if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks) {
    196             if( $this->mincolor != '' ) {
    197                 $aImg->PushColor($this->mincolor);
    198             }
    199             for($i=1; $i<=$nbrmin; ++$i) {
    200                 if( ($i % $skip) == 0 ) {
    201                     continue;
    202                 }
    203                 $xt=round($i*$min_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0];
    204                 $yt=$aPos-round($i*$min_step_abs*sin($aAxisAngle));
    205                 $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy);
    206             }
    207             if( $this->mincolor != '' ) {
    208                 $aImg->PopColor();
    209             }
    210         }
     134        // Prepare to draw linear ticks
     135        $maj_step_abs = abs($aScale->scale_factor*$this->major_step);   
     136        $min_step_abs = abs($aScale->scale_factor*$this->minor_step);   
     137        $nbrmaj = floor(($aScale->world_abs_size)/$maj_step_abs);
     138        $nbrmin = floor(($aScale->world_abs_size)/$min_step_abs);
     139        $skip = round($nbrmin/$nbrmaj); // Don't draw minor ontop of major
     140
     141        // Draw major ticks
     142        $ticklen2=$this->major_abs_size;
     143        $dx=round(sin($aAxisAngle)*$ticklen2);
     144        $dy=round(cos($aAxisAngle)*$ticklen2);
     145        $label=$aScale->scale[0]+$this->major_step;
     146               
     147        $aImg->SetLineWeight($this->weight);
     148        // NEW
     149        $aMajPos = array();     
     150        $aMajLabel = array();   
     151        for($i=1; $i<=$nbrmaj; ++$i) {
     152            $xt=round($i*$maj_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0];
     153            $yt=$aPos-round($i*$maj_step_abs*sin($aAxisAngle));
     154
     155            if( $this->label_formfunc != "" ) {
     156                $f=$this->label_formfunc;
     157                $l = call_user_func($f,$label);
     158            }
     159            else
     160                $l = $label;
     161
     162            $aMajLabel[]=$l;
     163            $label += $this->major_step;
     164            $grid[]=$xt;
     165            $grid[]=$yt;
     166            $aMajPos[($i-1)*2]=$xt+2*$dx;
     167            $aMajPos[($i-1)*2+1]=$yt-$aImg->GetFontheight()/2;                         
     168            if( !$this->supress_tickmarks ) {
     169                if( $this->majcolor!="" ) $aImg->PushColor($this->majcolor);
     170                $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy);
     171                if( $this->majcolor!="" ) $aImg->PopColor();
     172            }
     173        }
     174
     175        // Draw minor ticks
     176        $ticklen2=$this->minor_abs_size;
     177        $dx=round(sin($aAxisAngle)*$ticklen2);
     178        $dy=round(cos($aAxisAngle)*$ticklen2);
     179        if( !$this->supress_tickmarks && !$this->supress_minor_tickmarks)       {
     180            if( $this->mincolor!="" ) $aImg->PushColor($this->mincolor);                                               
     181            for($i=1; $i<=$nbrmin; ++$i) {
     182                if( ($i % $skip) == 0 ) continue;
     183                $xt=round($i*$min_step_abs*cos($aAxisAngle))+$aScale->scale_abs[0];
     184                $yt=$aPos-round($i*$min_step_abs*sin($aAxisAngle));
     185                $aImg->Line($xt+$dx,$yt+$dy,$xt-$dx,$yt-$dy);
     186            }
     187            if( $this->mincolor!="" ) $aImg->PopColor();
     188        }
    211189    }
    212190}
    213191
     192       
    214193
    215194//===================================================
     
    219198class RadarAxis extends AxisPrototype {
    220199    public $title=null;
    221     private $title_color='navy';
     200    private $title_color="navy";
    222201    private $len=0;
    223 
    224     function __construct($img,$aScale,$color=array(0,0,0)) {
    225         parent::__construct($img,$aScale,$color);
    226         $this->len = $img->plotheight;
    227         $this->title = new Text();
    228         $this->title->SetFont(FF_FONT1,FS_BOLD);
    229         $this->color = array(0,0,0);
    230     }
    231 
    232     // Stroke the axis
    233     // $pos    = Vertical position of axis
     202//---------------
     203// CONSTRUCTOR
     204    function RadarAxis($img,$aScale,$color=array(0,0,0)) {
     205        parent::Axis($img,$aScale,$color);
     206        $this->len=$img->plotheight;
     207        $this->title = new Text();
     208        $this->title->SetFont(FF_FONT1,FS_BOLD);
     209        $this->color = array(0,0,0);
     210    }
     211//---------------
     212// PUBLIC METHODS       
     213    function SetTickLabels($aLabelArray,$aLabelColorArray=null) {
     214        $this->ticks_label = $aLabelArray;
     215        $this->ticks_label_colors = $aLabelColorArray;
     216    }
     217       
     218       
     219    // Stroke the axis
     220    // $pos                     = Vertical position of axis
    234221    // $aAxisAngle = Axis angle
    235     // $grid   = Returns an array with positions used to draw the grid
    236     // $lf   = Label flag, TRUE if the axis should have labels
     222    // $grid                    = Returns an array with positions used to draw the grid
     223    //  $lf                     = Label flag, TRUE if the axis should have labels
    237224    function Stroke($pos,$aAxisAngle,&$grid,$title,$lf) {
    238         $this->img->SetColor($this->color);
    239 
    240         // Determine end points for the axis
    241         $x=round($this->scale->world_abs_size*cos($aAxisAngle)+$this->scale->scale_abs[0]);
    242         $y=round($pos-$this->scale->world_abs_size*sin($aAxisAngle));
    243 
    244         // Draw axis
    245         $this->img->SetColor($this->color);
    246         $this->img->SetLineWeight($this->weight);
    247         if( !$this->hide ) {
    248             $this->img->Line($this->scale->scale_abs[0],$pos,$x,$y);
    249         }
    250 
    251         $this->scale->ticks->Stroke($this->img,$grid,$pos,$aAxisAngle,$this->scale,$majpos,$majlabel);
    252         $ncolor=0;
    253         if( isset($this->ticks_label_colors) ) {
    254             $ncolor=count($this->ticks_label_colors);
    255         }
    256 
    257         // Draw labels
    258         if( $lf && !$this->hide ) {
    259             $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
    260             $this->img->SetTextAlign('left','top');
    261             $this->img->SetColor($this->label_color);
    262 
    263             // majpos contains (x,y) coordinates for labels
    264             if( ! $this->hide_labels ) {
    265                 $n = floor(count($majpos)/2);
    266                 for($i=0; $i < $n; ++$i) {
    267                     // Set specific label color if specified
    268                     if( $ncolor > 0 ) {
    269                         $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]);
    270                     }
    271 
    272                     if( $this->ticks_label != null && isset($this->ticks_label[$i]) ) {
    273                         $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$this->ticks_label[$i]);
    274                     }
    275                     else {
    276                         $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$majlabel[$i]);
    277                     }
    278                 }
    279             }
    280         }
    281         $this->_StrokeAxisTitle($pos,$aAxisAngle,$title);
    282     }
    283 
     225        $this->img->SetColor($this->color);
     226               
     227        // Determine end points for the axis
     228        $x=round($this->scale->world_abs_size*cos($aAxisAngle)+$this->scale->scale_abs[0]);
     229        $y=round($pos-$this->scale->world_abs_size*sin($aAxisAngle));
     230               
     231        // Draw axis
     232        $this->img->SetColor($this->color);
     233        $this->img->SetLineWeight($this->weight);
     234        if( !$this->hide )
     235            $this->img->Line($this->scale->scale_abs[0],$pos,$x,$y);
     236       
     237        $this->scale->ticks->Stroke($this->img,$grid,$pos,$aAxisAngle,$this->scale,$majpos,$majlabel);
     238        $ncolor=0;
     239        if( isset($this->ticks_label_colors) )
     240            $ncolor=count($this->ticks_label_colors);
     241               
     242        // Draw labels
     243        if( $lf && !$this->hide ) {
     244            $this->img->SetFont($this->font_family,$this->font_style,$this->font_size);
     245            $this->img->SetTextAlign("left","top");
     246            $this->img->SetColor($this->label_color);
     247                       
     248            // majpos contains (x,y) coordinates for labels
     249            if( ! $this->hide_labels ) {
     250                $n = floor(count($majpos)/2);
     251                for($i=0; $i < $n; ++$i) {
     252                    // Set specific label color if specified
     253                    if( $ncolor > 0 )
     254                        $this->img->SetColor($this->ticks_label_colors[$i % $ncolor]);
     255                   
     256                    if( $this->ticks_label != null && isset($this->ticks_label[$i]) )
     257                        $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$this->ticks_label[$i]);
     258                    else
     259                        $this->img->StrokeText($majpos[$i*2],$majpos[$i*2+1],$majlabel[$i]);
     260                }
     261            }
     262        }
     263        $this->_StrokeAxisTitle($pos,$aAxisAngle,$title);
     264    }
     265//---------------
     266// PRIVATE METHODS     
     267       
    284268    function _StrokeAxisTitle($pos,$aAxisAngle,$title) {
    285         $this->title->Set($title);
    286         $marg=6+$this->title->margin;
    287         $xt=round(($this->scale->world_abs_size+$marg)*cos($aAxisAngle)+$this->scale->scale_abs[0]);
    288         $yt=round($pos-($this->scale->world_abs_size+$marg)*sin($aAxisAngle));
    289 
    290         // Position the axis title.
    291         // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
    292         // that intersects with the extension of the corresponding axis. The code looks a little
    293         // bit messy but this is really the only way of having a reasonable position of the
    294         // axis titles.
    295         if( $this->title->iWordwrap > 0 ) {
    296             $title = wordwrap($title,$this->title->iWordwrap,"\n");
    297         }
    298 
    299         $h=$this->img->GetTextHeight($title)*1.2;
    300         $w=$this->img->GetTextWidth($title)*1.2;
    301 
    302         while( $aAxisAngle > 2*M_PI )
    303             $aAxisAngle -= 2*M_PI;
    304 
    305         // Around 3 a'clock
    306         if( $aAxisAngle>=7*M_PI/4 || $aAxisAngle <= M_PI/4 ) $dx=-0.15; // Small trimming to make the dist to the axis more even
    307 
    308         // Around 12 a'clock
    309         if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dx=($aAxisAngle-M_PI/4)*2/M_PI;
    310 
    311         // Around 9 a'clock
    312         if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dx=1;
    313 
    314         // Around 6 a'clock
    315         if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dx=(1-($aAxisAngle-M_PI*5/4)*2/M_PI);
    316 
    317         if( $aAxisAngle>=7*M_PI/4 ) $dy=(($aAxisAngle-M_PI)-3*M_PI/4)*2/M_PI;
    318         if( $aAxisAngle<=M_PI/12 ) $dy=(0.5-$aAxisAngle*2/M_PI);
    319         if( $aAxisAngle<=M_PI/4 && $aAxisAngle > M_PI/12) $dy=(1-$aAxisAngle*2/M_PI);
    320         if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dy=1;
    321         if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dy=(1-($aAxisAngle-3*M_PI/4)*2/M_PI);
    322         if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dy=0;
    323 
    324         if( !$this->hide ) {
    325             $this->title->Stroke($this->img,$xt-$dx*$w,$yt-$dy*$h,$title);
    326         }
    327     }
    328 
     269        $this->title->Set($title);
     270        $marg=6+$this->title->margin;
     271        $xt=round(($this->scale->world_abs_size+$marg)*cos($aAxisAngle)+$this->scale->scale_abs[0]);
     272        $yt=round($pos-($this->scale->world_abs_size+$marg)*sin($aAxisAngle));
     273
     274        // Position the axis title.
     275        // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
     276        // that intersects with the extension of the corresponding axis. The code looks a little
     277        // bit messy but this is really the only way of having a reasonable position of the
     278        // axis titles.
     279        if( $this->title->iWordwrap > 0 ) {
     280            $title = wordwrap($title,$this->title->iWordwrap,"\n");
     281        }
     282
     283        $h=$this->img->GetTextHeight($title)*1.2;
     284        $w=$this->img->GetTextWidth($title)*1.2;
     285
     286        while( $aAxisAngle > 2*M_PI ) $aAxisAngle -= 2*M_PI;
     287       
     288        // Around 3 a'clock
     289        if( $aAxisAngle>=7*M_PI/4 || $aAxisAngle <= M_PI/4 ) $dx=-0.15; // Small trimming to make the dist to the axis more even
     290        // Around 12 a'clock
     291        if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dx=($aAxisAngle-M_PI/4)*2/M_PI;
     292        // Around 9 a'clock
     293        if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dx=1;
     294        // Around 6 a'clock
     295        if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dx=(1-($aAxisAngle-M_PI*5/4)*2/M_PI);
     296               
     297        if( $aAxisAngle>=7*M_PI/4 ) $dy=(($aAxisAngle-M_PI)-3*M_PI/4)*2/M_PI;
     298        if( $aAxisAngle<=M_PI/12 ) $dy=(0.5-$aAxisAngle*2/M_PI);
     299        if( $aAxisAngle<=M_PI/4 && $aAxisAngle > M_PI/12) $dy=(1-$aAxisAngle*2/M_PI);
     300        if( $aAxisAngle>=M_PI/4 && $aAxisAngle <= 3*M_PI/4 ) $dy=1;
     301        if( $aAxisAngle>=3*M_PI/4 && $aAxisAngle <= 5*M_PI/4 ) $dy=(1-($aAxisAngle-3*M_PI/4)*2/M_PI);
     302        if( $aAxisAngle>=5*M_PI/4 && $aAxisAngle <= 7*M_PI/4 ) $dy=0;
     303               
     304        if( !$this->hide ) {
     305            $this->title->Stroke($this->img,$xt-$dx*$w,$yt-$dy*$h,$title);
     306        }
     307    }
     308               
     309       
    329310} // Class
    330311
     
    339320    private $show=false, $weight=1;
    340321
    341     function __construct() {
    342         // Empty
    343     }
    344 
     322//------------
     323// CONSTRUCTOR
     324    function RadarGrid() {
     325    }
     326
     327// PUBLIC METHODS
    345328    function SetColor($aMajColor) {
    346         $this->grid_color = $aMajColor;
    347     }
    348 
     329        $this->grid_color = $aMajColor;
     330    }
     331       
    349332    function SetWeight($aWeight) {
    350         $this->weight=$aWeight;
    351     }
    352 
     333        $this->weight=$aWeight;
     334    }
     335       
    353336    // Specify if grid should be dashed, dotted or solid
    354337    function SetLineStyle($aType) {
    355         $this->type = $aType;
    356     }
    357 
     338        $this->type = $aType;
     339    }
     340       
    358341    // Decide if both major and minor grid should be displayed
    359342    function Show($aShowMajor=true) {
    360         $this->show=$aShowMajor;
    361     }
    362 
     343        $this->show=$aShowMajor;
     344    }
     345   
     346//----------------
     347// PRIVATE METHODS     
    363348    function Stroke($img,$grid) {
    364         if( !$this->show ) {
    365             return;
    366         }
    367 
    368         $nbrticks = count($grid[0])/2;
    369         $nbrpnts = count($grid);
    370         $img->SetColor($this->grid_color);
    371         $img->SetLineWeight($this->weight);
    372 
    373         for($i=0; $i<$nbrticks; ++$i) {
    374             for($j=0; $j<$nbrpnts; ++$j) {
    375                 $pnts[$j*2]=$grid[$j][$i*2];
    376                 $pnts[$j*2+1]=$grid[$j][$i*2+1];
    377             }
    378             for($k=0; $k<$nbrpnts; ++$k ){
    379                 $l=($k+1)%$nbrpnts;
    380                 if( $this->type == 'solid' )
    381                     $img->Line($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1]);
    382                 elseif( $this->type == 'dotted' )
    383                     $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],1,6);
    384                 elseif( $this->type == 'dashed' )
    385                     $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],2,4);
    386                 elseif( $this->type == 'longdashed' )
    387                     $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],8,6);
    388             }
    389             $pnts=array();
    390         }
     349        if( !$this->show ) return;
     350        $nbrticks = count($grid[0])/2;
     351        $nbrpnts = count($grid);
     352        $img->SetColor($this->grid_color);
     353        $img->SetLineWeight($this->weight);
     354        for($i=0; $i<$nbrticks; ++$i) {
     355            for($j=0; $j<$nbrpnts; ++$j) {
     356                $pnts[$j*2]=$grid[$j][$i*2];
     357                $pnts[$j*2+1]=$grid[$j][$i*2+1];
     358            }
     359            for($k=0; $k<$nbrpnts; ++$k ){
     360                $l=($k+1)%$nbrpnts;
     361                if( $this->type == "solid" )
     362                    $img->Line($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1]);
     363                elseif( $this->type == "dotted" )
     364                    $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],1,6);
     365                elseif( $this->type == "dashed" )
     366                    $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],2,4);
     367                elseif( $this->type == "longdashed" )
     368                    $img->DashedLine($pnts[$k*2],$pnts[$k*2+1],$pnts[$l*2],$pnts[$l*2+1],8,6);
     369            }
     370            $pnts=array();
     371        }
    391372    }
    392373} // Class
     
    399380class RadarPlot {
    400381    public $mark=null;
    401     public $legend='';
    402     public $legendcsimtarget='';
    403     public $legendcsimalt='';
    404     public $csimtargets=array(); // Array of targets for CSIM
    405     public $csimareas="";   // Resultant CSIM area tags
    406     public $csimalts=null;   // ALT:s for corresponding target
     382    public $legend="";
    407383    private $data=array();
    408384    private $fill=false, $fill_color=array(200,170,180);
     
    410386    private $weight=1;
    411387    private $linestyle='solid';
    412 
    413     //---------------
    414     // CONSTRUCTOR
    415     function __construct($data) {
    416         $this->data = $data;
    417         $this->mark = new PlotMark();
    418     }
    419 
     388//---------------
     389// CONSTRUCTOR
     390    function RadarPlot($data) {
     391        $this->data = $data;
     392        $this->mark = new PlotMark();
     393    }
     394
     395//---------------
     396// PUBLIC METHODS       
    420397    function Min() {
    421         return Min($this->data);
    422     }
    423 
     398        return Min($this->data);
     399    }
     400       
    424401    function Max() {
    425         return Max($this->data);
    426     }
    427 
     402        return Max($this->data);
     403    }
     404       
    428405    function SetLegend($legend) {
    429         $this->legend=$legend;
     406        $this->legend=$legend;
    430407    }
    431408
    432409    function SetLineStyle($aStyle) {
    433         $this->linestyle=$aStyle;
    434     }
    435 
     410        $this->linestyle=$aStyle;
     411    }
     412       
    436413    function SetLineWeight($w) {
    437         $this->weight=$w;
    438     }
    439 
     414        $this->weight=$w;
     415    }
     416               
    440417    function SetFillColor($aColor) {
    441         $this->fill_color = $aColor;
    442         $this->fill = true;
    443     }
    444 
     418        $this->fill_color = $aColor;
     419        $this->fill = true;             
     420    }
     421   
    445422    function SetFill($f=true) {
    446         $this->fill = $f;
    447     }
    448 
     423        $this->fill = $f;
     424    }
     425   
    449426    function SetColor($aColor,$aFillColor=false) {
    450         $this->color = $aColor;
    451         if( $aFillColor ) {
    452             $this->SetFillColor($aFillColor);
    453             $this->fill = true;
    454         }
    455     }
    456 
    457     // Set href targets for CSIM
    458     function SetCSIMTargets($aTargets,$aAlts=null) {
    459         $this->csimtargets=$aTargets;
    460         $this->csimalts=$aAlts;
    461     }
    462 
    463     // Get all created areas
     427        $this->color = $aColor;
     428        if( $aFillColor ) {
     429            $this->SetFillColor($aFillColor);
     430            $this->fill = true;
     431        }
     432    }
     433       
    464434    function GetCSIMareas() {
    465         return $this->csimareas;
    466     }
    467 
     435        JpGraphError::RaiseL(18001);
     436//("Client side image maps not supported for RadarPlots.");
     437    }
     438       
    468439    function Stroke($img, $pos, $scale, $startangle) {
    469         $nbrpnts = count($this->data);
    470         $astep=2*M_PI/$nbrpnts;
    471         $a=$startangle;
    472 
    473         for($i=0; $i<$nbrpnts; ++$i) {
    474 
    475             // Rotate each non null point to the correct axis-angle
    476             $cs=$scale->RelTranslate($this->data[$i]);
    477             $x=round($cs*cos($a)+$scale->scale_abs[0]);
    478             $y=round($pos-$cs*sin($a));
    479 
    480             $pnts[$i*2]=$x;
    481             $pnts[$i*2+1]=$y;
    482 
    483             // If the next point is null then we draw this polygon segment
    484             // to the center, skip the next and draw the next segment from
    485             // the center up to the point on the axis with the first non-null
    486             // value and continues from that point. Some additoinal logic is necessary
    487             // to handle the boundary conditions
    488             if( $i < $nbrpnts-1 ) {
    489                 if( is_null($this->data[$i+1]) ) {
    490                     $cs = 0;
    491                     $x=round($cs*cos($a)+$scale->scale_abs[0]);
    492                     $y=round($pos-$cs*sin($a));
    493                     $pnts[$i*2]=$x;
    494                     $pnts[$i*2+1]=$y;
    495                     $a += $astep;
    496                 }
    497             }
    498 
    499             $a += $astep;
    500         }
    501 
    502         if( $this->fill ) {
    503             $img->SetColor($this->fill_color);
    504             $img->FilledPolygon($pnts);
    505         }
    506 
    507         $img->SetLineWeight($this->weight);
    508         $img->SetColor($this->color);
    509         $img->SetLineStyle($this->linestyle);
    510         $pnts[] = $pnts[0];
    511         $pnts[] = $pnts[1];
    512         $img->Polygon($pnts);
    513         $img->SetLineStyle('solid'); // Reset line style to default
    514 
    515         // Add plotmarks on top
    516         if( $this->mark->show ) {
    517                         for($i=0; $i < $nbrpnts; ++$i) {
    518                     if( isset($this->csimtargets[$i]) ) {
    519                         $this->mark->SetCSIMTarget($this->csimtargets[$i]);
    520                         $this->mark->SetCSIMAlt($this->csimalts[$i]);
    521                         $this->mark->SetCSIMAltVal($pnts[$i*2], $pnts[$i*2+1]);
    522                         $this->mark->Stroke($img, $pnts[$i*2], $pnts[$i*2+1]);
    523                         $this->csimareas .= $this->mark->GetCSIMAreas();
    524                     }
    525                     else {
    526                                         $this->mark->Stroke($img,$pnts[$i*2],$pnts[$i*2+1]);
    527                     }
    528             }
    529         }
    530 
    531     }
    532 
     440        $nbrpnts = count($this->data);
     441        $astep=2*M_PI/$nbrpnts;         
     442        $a=$startangle;
     443               
     444        $nulls=0;
     445        for($i=0; $i<$nbrpnts; ++$i) {
     446            if(!is_null($this->data[$i])) {
     447                // Rotate each non null point to the correct axis-angle
     448                $cs=$scale->RelTranslate($this->data[$i]);
     449                $x=round($cs*cos($a)+$scale->scale_abs[0]);
     450                $y=round($pos-$cs*sin($a));
     451                /*
     452                 // TODO: Update for proper LogScale
     453                 $c=log10($c);
     454                 $x=round(($c-$scale->scale[0])*$scale->scale_factor*cos($a)+$scale->scale_abs[0]);
     455                 $y=round($pos-($c-$scale->scale[0])*$scale->scale_factor*sin($a));             
     456                */
     457                $pnts[($i-$nulls)*2]=$x;
     458                $pnts[($i-$nulls)*2+1]=$y;
     459            }
     460            else {
     461                ++$nulls;
     462            }
     463            $a += $astep;
     464        }
     465
     466        if( $this->fill ) {
     467            $img->SetColor($this->fill_color);
     468            $img->FilledPolygon($pnts);
     469        }
     470        $img->SetLineWeight($this->weight);
     471        $img->SetColor($this->color);
     472        $img->SetLineStyle($this->linestyle);
     473        $pnts[]=$pnts[0];
     474        $pnts[]=$pnts[1];
     475        $img->Polygon($pnts);
     476        $img->SetLineStyle('solid'); // Reset line style to default
     477
     478        // Add plotmarks on top
     479        if( $this->mark->show ) {
     480            for($i=0; $i < $nbrpnts; ++$i) {
     481                $this->mark->Stroke($img,$pnts[$i*2],$pnts[$i*2+1]);
     482            }
     483        }
     484
     485    }
     486       
     487//---------------
     488// PRIVATE METHODS
    533489    function GetCount() {
    534         return count($this->data);
    535     }
    536 
     490        return count($this->data);
     491    }
     492       
    537493    function Legend($graph) {
    538         if( $this->legend == '' ) {
    539             return;
    540         }
    541         if( $this->fill ) {
    542             $graph->legend->Add($this->legend,$this->fill_color,$this->mark);
    543         } else {
    544             $graph->legend->Add($this->legend,$this->color,$this->mark);
    545         }
    546     }
    547 
     494        if( $this->legend=="" ) return;
     495        if( $this->fill )
     496            $graph->legend->Add($this->legend,$this->fill_color,$this->mark);
     497        else
     498            $graph->legend->Add($this->legend,$this->color,$this->mark);       
     499    }
     500       
    548501} // Class
    549502
     
    555508    public $grid,$axis=null;
    556509    private $posx,$posy;
    557     private $len;
     510    private $len;               
    558511    private $axis_title=null;
    559 
    560     function __construct($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) {
    561         parent::__construct($width,$height,$cachedName,$timeout,$inline);
    562         $this->posx = $width/2;
    563         $this->posy = $height/2;
    564         $this->len = min($width,$height)*0.35;
    565         $this->SetColor(array(255,255,255));
    566         $this->SetTickDensity(TICKD_NORMAL);
    567         $this->SetScale('lin');
    568         $this->SetGridDepth(DEPTH_FRONT);
     512//---------------
     513// CONSTRUCTOR
     514    function RadarGraph($width=300,$height=200,$cachedName="",$timeout=0,$inline=1) {
     515        $this->Graph($width,$height,$cachedName,$timeout,$inline);
     516        $this->posx=$width/2;
     517        $this->posy=$height/2;
     518        $this->len=min($width,$height)*0.35;
     519        $this->SetColor(array(255,255,255));
     520        $this->SetTickDensity(TICKD_NORMAL);
     521        $this->SetScale("lin");
     522        $this->SetGridDepth(DEPTH_FRONT);
     523
     524    }
     525
     526//---------------
     527// PUBLIC METHODS
     528    function SupressTickMarks($f=true) {
     529        if( ERR_DEPRECATED )
     530            JpGraphError::RaiseL(18002);
     531//('RadarGraph::SupressTickMarks() is deprecated. Use HideTickMarks() instead.');
     532        $this->axis->scale->ticks->SupressTickMarks($f);
    569533    }
    570534
    571535    function HideTickMarks($aFlag=true) {
    572         $this->axis->scale->ticks->SupressTickMarks($aFlag);
    573     }
    574 
     536                $this->axis->scale->ticks->SupressTickMarks($aFlag);
     537    }
     538   
    575539    function ShowMinorTickmarks($aFlag=true) {
    576         $this->yscale->ticks->SupressMinorTickMarks(!$aFlag);
    577     }
    578 
     540        $this->yscale->ticks->SupressMinorTickMarks(!$aFlag);
     541    }
     542       
    579543    function SetScale($axtype,$ymin=1,$ymax=1,$dummy1=null,$dumy2=null) {
    580         if( $axtype != 'lin' && $axtype != 'log' ) {
    581             JpGraphError::RaiseL(18003,$axtype);
    582             //("Illegal scale for radarplot ($axtype). Must be \"lin\" or \"log\"");
    583         }
    584         if( $axtype == 'lin' ) {
    585             $this->yscale = new LinearScale($ymin,$ymax);
    586             $this->yscale->ticks = new RadarLinearTicks();
    587             $this->yscale->ticks->SupressMinorTickMarks();
    588         }
    589         elseif( $axtype == 'log' ) {
    590             $this->yscale = new LogScale($ymin,$ymax);
    591             $this->yscale->ticks = new RadarLogTicks();
    592         }
    593 
    594         $this->axis = new RadarAxis($this->img,$this->yscale);
    595         $this->grid = new RadarGrid();
     544        if( $axtype != "lin" && $axtype != "log" ) {
     545            JpGraphError::RaiseL(18003,$axtype);
     546//("Illegal scale for radarplot ($axtype). Must be \"lin\" or \"log\"");
     547        }
     548        if( $axtype=="lin" ) {
     549            $this->yscale = new LinearScale($ymin,$ymax);
     550            $this->yscale->ticks = new RadarLinearTicks();
     551            $this->yscale->ticks->SupressMinorTickMarks();
     552        }
     553        elseif( $axtype=="log" ) {
     554            $this->yscale = new LogScale($ymin,$ymax);
     555            $this->yscale->ticks = new RadarLogTicks();
     556        }
     557               
     558        $this->axis = new RadarAxis($this->img,$this->yscale);
     559        $this->grid = new RadarGrid();         
    596560    }
    597561
    598562    function SetSize($aSize) {
    599         if( $aSize < 0.1 || $aSize>1 ) {
    600             JpGraphError::RaiseL(18004,$aSize);
    601             //("Radar Plot size must be between 0.1 and 1. (Your value=$s)");
    602         }
    603         $this->len=min($this->img->width,$this->img->height)*$aSize/2;
     563        if( $aSize < 0.1 || $aSize>1 )
     564            JpGraphError::RaiseL(18004,$aSize);
     565//("Radar Plot size must be between 0.1 and 1. (Your value=$s)");
     566        $this->len=min($this->img->width,$this->img->height)*$aSize/2;
    604567    }
    605568
    606569    function SetPlotSize($aSize) {
    607         $this->SetSize($aSize);
     570        $this->SetSize($aSize);
    608571    }
    609572
    610573    function SetTickDensity($densy=TICKD_NORMAL,$dummy1=null) {
    611         $this->ytick_factor=25;
    612         switch( $densy ) {
    613             case TICKD_DENSE:
    614                 $this->ytick_factor=12;
    615                 break;
    616             case TICKD_NORMAL:
    617                 $this->ytick_factor=25;
    618                 break;
    619             case TICKD_SPARSE:
    620                 $this->ytick_factor=40;
    621                 break;
    622             case TICKD_VERYSPARSE:
    623                 $this->ytick_factor=70;
    624                 break;
    625             default:
    626                 JpGraphError::RaiseL(18005,$densy);
    627                 //("RadarPlot Unsupported Tick density: $densy");
    628         }
     574        $this->ytick_factor=25;         
     575        switch( $densy ) {
     576            case TICKD_DENSE:
     577                $this->ytick_factor=12;                 
     578            break;
     579            case TICKD_NORMAL:
     580                $this->ytick_factor=25;                 
     581            break;
     582            case TICKD_SPARSE:
     583                $this->ytick_factor=40;                 
     584            break;
     585            case TICKD_VERYSPARSE:
     586                $this->ytick_factor=70;                 
     587            break;             
     588            default:
     589                JpGraphError::RaiseL(18005,$densy);
     590//("RadarPlot Unsupported Tick density: $densy");
     591        }
    629592    }
    630593
    631594    function SetPos($px,$py=0.5) {
    632         $this->SetCenter($px,$py);
     595        $this->SetCenter($px,$py);
    633596    }
    634597
    635598    function SetCenter($px,$py=0.5) {
    636         if( $px >= 0 && $px <= 1 ) {
    637                 $this->posx = $this->img->width*$px;
    638         }
    639         else {
    640                 $this->posx = $px;
    641         }
    642         if( $py >= 0 && $py <= 1 ) {
    643                 $this->posy = $this->img->height*$py;
    644         }
    645         else {
    646                 $this->posy = $py;
    647         }
    648     }
    649 
    650     function SetColor($aColor) {
    651         $this->SetMarginColor($aColor);
    652     }
    653 
    654     function SetTitles($aTitleArray) {
    655         $this->axis_title = $aTitleArray;
    656     }
    657 
    658     function Add($aPlot) {
    659         if( $aPlot == null ) {
    660             JpGraphError::RaiseL(25010);//("Graph::Add() You tried to add a null plot to the graph.");
    661         }
    662         if( is_array($aPlot) && count($aPlot) > 0 ) {
    663             $cl = $aPlot[0];
    664         }
    665         else {
    666             $cl = $aPlot;
    667         }
    668 
    669         if( $cl instanceof Text ) $this->AddText($aPlot);
    670         elseif( class_exists('IconPlot',false) && ($cl instanceof IconPlot) ) $this->AddIcon($aPlot);
    671         else {
    672             $this->plots[] = $aPlot;
    673         }
    674     }
    675 
     599        assert($px > 0 && $py > 0 );
     600        $this->posx=$this->img->width*$px;
     601        $this->posy=$this->img->height*$py;
     602    }
     603
     604    function SetColor($c) {
     605        $this->SetMarginColor($c);
     606    }
     607                       
     608    function SetTitles($title) {
     609        $this->axis_title = $title;
     610    }
     611
     612    function Add($splot) {
     613        $this->plots[]=$splot;
     614    }
     615       
    676616    function GetPlotsYMinMax($aPlots) {
    677         $min=$aPlots[0]->Min();
    678         $max=$aPlots[0]->Max();
    679         foreach( $this->plots as $p ) {
    680             $max=max($max,$p->Max());
    681             $min=min($min,$p->Min());
    682         }
    683         if( $min < 0 ) {
    684             JpGraphError::RaiseL(18006,$min);
    685             //("Minimum data $min (Radar plots should only be used when all data points > 0)");
    686         }
    687         return array($min,$max);
    688     }
    689 
    690     function StrokeIcons() {
    691         if( $this->iIcons != null ) {
    692                 $n = count($this->iIcons);
    693                 for( $i=0; $i < $n; ++$i ) {
    694                 $this->iIcons[$i]->Stroke($this->img);
    695                 }
    696         }
    697     }
    698 
    699         function StrokeTexts() {
    700         if( $this->texts != null ) {
    701                         $n = count($this->texts);
    702             for( $i=0; $i < $n; ++$i ) {
    703                 $this->texts[$i]->Stroke($this->img);
    704             }
    705         }
    706     }
     617        $min=$aPlots[0]->Min();
     618        $max=$aPlots[0]->Max();
     619        foreach( $this->plots as $p ) {
     620            $max=max($max,$p->Max());
     621            $min=min($min,$p->Min());
     622        }
     623        if( $min < 0 )
     624            JpGraphError::RaiseL(18006,$min);
     625//("Minimum data $min (Radar plots should only be used when all data points > 0)");
     626        return array($min,$max);
     627    }   
    707628
    708629    // Stroke the Radar graph
    709     function Stroke($aStrokeFileName='') {
    710 
    711         // If the filename is the predefined value = '_csim_special_'
    712         // we assume that the call to stroke only needs to do enough
    713         // to correctly generate the CSIM maps.
    714         // We use this variable to skip things we don't strictly need
    715         // to do to generate the image map to improve performance
    716         // a best we can. Therefor you will see a lot of tests !$_csim in the
    717         // code below.
    718         $_csim = ( $aStrokeFileName === _CSIM_SPECIALFILE );
    719 
    720         // We need to know if we have stroked the plot in the
    721         // GetCSIMareas. Otherwise the CSIM hasn't been generated
    722         // and in the case of GetCSIM called before stroke to generate
    723         // CSIM without storing an image to disk GetCSIM must call Stroke.
    724         $this->iHasStroked = true;
    725 
    726         $n = count($this->plots);
    727         // Set Y-scale
    728 
    729         if( !$this->yscale->IsSpecified() && count($this->plots) > 0 ) {
    730             list($min,$max) = $this->GetPlotsYMinMax($this->plots);
    731             $this->yscale->AutoScale($this->img,0,$max,$this->len/$this->ytick_factor);
    732         }
    733         elseif( $this->yscale->IsSpecified() &&
    734                 ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) {
    735 
    736             // The tick calculation will use the user suplied min/max values to determine
    737             // the ticks. If auto_ticks is false the exact user specifed min and max
    738             // values will be used for the scale.
    739             // If auto_ticks is true then the scale might be slightly adjusted
    740             // so that the min and max values falls on an even major step.
    741             $min = $this->yscale->scale[0];
    742             $max = $this->yscale->scale[1];
    743             $this->yscale->AutoScale($this->img,$min,$max,
    744                                      $this->len/$this->ytick_factor,
    745                                      $this->yscale->auto_ticks);
    746         }
    747 
    748         // Set start position end length of scale (in absolute pixels)
    749         $this->yscale->SetConstants($this->posx,$this->len);
    750 
    751         // We need as many axis as there are data points
    752         $nbrpnts=$this->plots[0]->GetCount();
    753 
    754         // If we have no titles just number the axis 1,2,3,...
    755         if( $this->axis_title==null ) {
    756             for($i=0; $i < $nbrpnts; ++$i ) {
    757                 $this->axis_title[$i] = $i+1;
    758             }
    759         }
    760         elseif( count($this->axis_title) < $nbrpnts) {
    761             JpGraphError::RaiseL(18007);
    762             // ("Number of titles does not match number of points in plot.");
    763         }
    764         for( $i=0; $i < $n; ++$i ) {
    765             if( $nbrpnts != $this->plots[$i]->GetCount() ) {
    766                 JpGraphError::RaiseL(18008);
    767                 //("Each radar plot must have the same number of data points.");
    768             }
    769         }
    770 
    771         if( !$_csim ) {
    772                 if( $this->background_image != '' ) {
    773                 $this->StrokeFrameBackground();
    774                 }
    775                 else {
    776                 $this->StrokeFrame();
    777                 $this->StrokeBackgroundGrad();
    778                 }
    779         }
    780         $astep=2*M_PI/$nbrpnts;
    781 
    782                 if( !$_csim ) {
    783                 if( $this->iIconDepth == DEPTH_BACK ) {
    784                         $this->StrokeIcons();
    785                 }
    786 
    787 
    788                 // Prepare legends
    789             for($i=0; $i < $n; ++$i) {
    790                     $this->plots[$i]->Legend($this);
    791                 }
    792             $this->legend->Stroke($this->img);
    793                 $this->footer->Stroke($this->img);
    794                 }
    795 
    796                 if( !$_csim ) {
    797                 if( $this->grid_depth == DEPTH_BACK ) {
    798                     // Draw axis and grid
    799                     for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) {
    800                         $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0);
    801                     }
    802                 $this->grid->Stroke($this->img,$grid);
    803                 }
    804             if( $this->iIconDepth == DEPTH_BACK ) {
    805                 $this->StrokeIcons();
    806             }
    807 
    808                 }
    809 
    810         // Plot points
    811         $a=M_PI/2;
    812         for($i=0; $i < $n; ++$i ) {
    813             $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a);
    814         }
    815 
    816         if( !$_csim ) {
    817             if( $this->grid_depth != DEPTH_BACK ) {
    818                 // Draw axis and grid
    819                 for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) {
    820                    $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0);
    821                 }
    822                 $this->grid->Stroke($this->img,$grid);
    823             }
    824 
    825                 $this->StrokeTitles();
    826                 $this->StrokeTexts();
    827                 if( $this->iIconDepth == DEPTH_FRONT ) {
    828                         $this->StrokeIcons();
    829                 }
    830                 }
    831 
    832         // Should we do any final image transformation
    833         if( $this->iImgTrans && !$_csim ) {
    834             if( !class_exists('ImgTrans',false) ) {
    835                 require_once('jpgraph_imgtrans.php');
    836             }
    837 
    838             $tform = new ImgTrans($this->img->img);
    839             $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
    840             $this->iImgTransDirection,$this->iImgTransHighQ,
    841             $this->iImgTransMinSize,$this->iImgTransFillColor,
    842             $this->iImgTransBorder);
    843         }
    844 
    845                 if( !$_csim ) {
    846                 // If the filename is given as the special "__handle"
    847                 // then the image handler is returned and the image is NOT
    848                 // streamed back
    849                 if( $aStrokeFileName == _IMG_HANDLER ) {
    850                     return $this->img->img;
    851                 }
    852                 else {
    853                     // Finally stream the generated picture
    854                     $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,$aStrokeFileName);
    855                 }
    856                 }
     630    function Stroke($aStrokeFileName="") {
     631        $n = count($this->plots);
     632        // Set Y-scale
     633        if( !$this->yscale->IsSpecified() && count($this->plots)>0 ) {
     634            list($min,$max) = $this->GetPlotsYMinMax($this->plots);
     635            $this->yscale->AutoScale($this->img,0,$max,$this->len/$this->ytick_factor);
     636        }
     637        elseif( $this->yscale->IsSpecified() &&
     638                ( $this->yscale->auto_ticks || !$this->yscale->ticks->IsSpecified()) ) {
     639            // The tick calculation will use the user suplied min/max values to determine
     640            // the ticks. If auto_ticks is false the exact user specifed min and max
     641            // values will be used for the scale.
     642            // If auto_ticks is true then the scale might be slightly adjusted
     643            // so that the min and max values falls on an even major step.
     644            $min = $this->yscale->scale[0];
     645            $max = $this->yscale->scale[1];
     646            $this->yscale->AutoScale($this->img,$min,$max,
     647                                     $this->len/$this->ytick_factor,
     648                                     $this->yscale->auto_ticks);
     649        }
     650
     651        // Set start position end length of scale (in absolute pixels)
     652        $this->yscale->SetConstants($this->posx,$this->len);
     653               
     654        // We need as many axis as there are data points
     655        $nbrpnts=$this->plots[0]->GetCount();
     656               
     657        // If we have no titles just number the axis 1,2,3,...
     658        if( $this->axis_title==null ) {
     659            for($i=0; $i < $nbrpnts; ++$i )
     660                $this->axis_title[$i] = $i+1;
     661        }
     662        elseif(count($this->axis_title)<$nbrpnts)
     663            JpGraphError::RaiseL(18007);
     664//("Number of titles does not match number of points in plot.");
     665        for($i=0; $i < $n; ++$i )
     666            if( $nbrpnts != $this->plots[$i]->GetCount() )
     667                JpGraphError::RaiseL(18008);
     668//("Each radar plot must have the same number of data points.");
     669
     670        if( $this->background_image != "" ) {
     671            $this->StrokeFrameBackground();
     672        }
     673        else { 
     674            $this->StrokeFrame();
     675        }
     676        $astep=2*M_PI/$nbrpnts;
     677
     678        // Prepare legends
     679        for($i=0; $i < $n; ++$i)
     680            $this->plots[$i]->Legend($this);
     681        $this->legend->Stroke($this->img);                     
     682        $this->footer->Stroke($this->img);                     
     683
     684        if( $this->grid_depth == DEPTH_BACK ) {
     685            // Draw axis and grid
     686            for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) {
     687                $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0);
     688            }   
     689        }
     690               
     691        // Plot points
     692        $a=M_PI/2;
     693        for($i=0; $i < $n; ++$i )
     694            $this->plots[$i]->Stroke($this->img, $this->posy, $this->yscale, $a);
     695               
     696        if( $this->grid_depth != DEPTH_BACK ) {
     697            // Draw axis and grid
     698            for( $i=0,$a=M_PI/2; $i < $nbrpnts; ++$i, $a += $astep ) {
     699                $this->axis->Stroke($this->posy,$a,$grid[$i],$this->axis_title[$i],$i==0);
     700            }   
     701        }
     702        $this->grid->Stroke($this->img,$grid);
     703        $this->StrokeTitles();
     704       
     705        // Stroke texts
     706        if( $this->texts != null ) {
     707            foreach( $this->texts as $t)
     708                $t->Stroke($this->img);
     709        }
     710
     711        // Should we do any final image transformation
     712        if( $this->iImgTrans ) {
     713            if( !class_exists('ImgTrans',false) ) {
     714                require_once('jpgraph_imgtrans.php');
     715            }
     716               
     717            $tform = new ImgTrans($this->img->img);
     718            $this->img->img = $tform->Skew3D($this->iImgTransHorizon,$this->iImgTransSkewDist,
     719                                             $this->iImgTransDirection,$this->iImgTransHighQ,
     720                                             $this->iImgTransMinSize,$this->iImgTransFillColor,
     721                                             $this->iImgTransBorder);
     722        }
     723       
     724        // If the filename is given as the special "__handle"
     725        // then the image handler is returned and the image is NOT
     726        // streamed back
     727        if( $aStrokeFileName == _IMG_HANDLER ) {
     728            return $this->img->img;
     729            }
     730        else {
     731            // Finally stream the generated picture                                     
     732            $this->cache->PutAndStream($this->img,$this->cache_name,$this->inline,
     733                                       $aStrokeFileName);               
     734        }
    857735    }
    858736} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_regstat.php

    r265 r267  
    1 <?php
     1<?php 
    22/*=======================================================================
    3  // File:        JPGRAPH_REGSTAT.PHP
    4  // Description: Regression and statistical analysis helper classes
    5  // Created:     2002-12-01
    6  // Ver:         $Id: jpgraph_regstat.php 1131 2009-03-11 20:08:24Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_REGSTAT.PHP
     4// Description: Regression and statistical analysis helper classes
     5// Created:     2002-12-01
     6// Ver:         $Id: jpgraph_regstat.php 781 2006-10-08 08:07:47Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212//------------------------------------------------------------------------
     
    1919
    2020    private $xdata,$ydata;   // Data vectors
    21     private $y2;   // 2:nd derivate of ydata
     21    private $y2;                 // 2:nd derivate of ydata     
    2222    private $n=0;
    2323
    24     function __construct($xdata,$ydata) {
    25         $this->y2 = array();
    26         $this->xdata = $xdata;
    27         $this->ydata = $ydata;
    28 
    29         $n = count($ydata);
    30         $this->n = $n;
    31         if( $this->n !== count($xdata) ) {
    32             JpGraphError::RaiseL(19001);
    33             //('Spline: Number of X and Y coordinates must be the same');
    34         }
    35 
    36         // Natural spline 2:derivate == 0 at endpoints
    37         $this->y2[0]    = 0.0;
    38         $this->y2[$n-1] = 0.0;
    39         $delta[0] = 0.0;
    40 
    41         // Calculate 2:nd derivate
    42         for($i=1; $i < $n-1; ++$i) {
    43             $d = ($xdata[$i+1]-$xdata[$i-1]);
    44             if( $d == 0  ) {
    45                 JpGraphError::RaiseL(19002);
    46                 //('Invalid input data for spline. Two or more consecutive input X-values are equal. Each input X-value must differ since from a mathematical point of view it must be a one-to-one mapping, i.e. each X-value must correspond to exactly one Y-value.');
    47             }
    48             $s = ($xdata[$i]-$xdata[$i-1])/$d;
    49             $p = $s*$this->y2[$i-1]+2.0;
    50             $this->y2[$i] = ($s-1.0)/$p;
    51             $delta[$i] = ($ydata[$i+1]-$ydata[$i])/($xdata[$i+1]-$xdata[$i]) -
    52             ($ydata[$i]-$ydata[$i-1])/($xdata[$i]-$xdata[$i-1]);
    53             $delta[$i] = (6.0*$delta[$i]/($xdata[$i+1]-$xdata[$i-1])-$s*$delta[$i-1])/$p;
    54         }
    55 
    56         // Backward substitution
    57         for( $j=$n-2; $j >= 0; --$j ) {
    58             $this->y2[$j] = $this->y2[$j]*$this->y2[$j+1] + $delta[$j];
    59         }
     24    function Spline($xdata,$ydata) {
     25        $this->y2 = array();
     26        $this->xdata = $xdata;
     27        $this->ydata = $ydata;
     28
     29        $n = count($ydata);
     30        $this->n = $n;
     31        if( $this->n !== count($xdata) ) {
     32            JpGraphError::RaiseL(19001);
     33//('Spline: Number of X and Y coordinates must be the same');
     34        }
     35
     36        // Natural spline 2:derivate == 0 at endpoints
     37        $this->y2[0]    = 0.0;
     38        $this->y2[$n-1] = 0.0;
     39        $delta[0] = 0.0;
     40
     41        // Calculate 2:nd derivate
     42        for($i=1; $i < $n-1; ++$i) {
     43            $d = ($xdata[$i+1]-$xdata[$i-1]);
     44            if( $d == 0  ) {
     45                JpGraphError::RaiseL(19002);
     46//('Invalid input data for spline. Two or more consecutive input X-values are equal. Each input X-value must differ since from a mathematical point of view it must be a one-to-one mapping, i.e. each X-value must correspond to exactly one Y-value.');
     47            }
     48            $s = ($xdata[$i]-$xdata[$i-1])/$d;
     49            $p = $s*$this->y2[$i-1]+2.0;
     50            $this->y2[$i] = ($s-1.0)/$p;
     51            $delta[$i] = ($ydata[$i+1]-$ydata[$i])/($xdata[$i+1]-$xdata[$i]) -
     52                         ($ydata[$i]-$ydata[$i-1])/($xdata[$i]-$xdata[$i-1]);
     53            $delta[$i] = (6.0*$delta[$i]/($xdata[$i+1]-$xdata[$i-1])-$s*$delta[$i-1])/$p;
     54        }
     55
     56        // Backward substitution
     57        for( $j=$n-2; $j >= 0; --$j ) {
     58            $this->y2[$j] = $this->y2[$j]*$this->y2[$j+1] + $delta[$j];
     59        }
    6060    }
    6161
    6262    // Return the two new data vectors
    6363    function Get($num=50) {
    64         $n = $this->n ;
    65         $step = ($this->xdata[$n-1]-$this->xdata[0]) / ($num-1);
    66         $xnew=array();
    67         $ynew=array();
    68         $xnew[0] = $this->xdata[0];
    69         $ynew[0] = $this->ydata[0];
    70         for( $j=1; $j < $num; ++$j ) {
    71             $xnew[$j] = $xnew[0]+$j*$step;
    72             $ynew[$j] = $this->Interpolate($xnew[$j]);
    73         }
    74         return array($xnew,$ynew);
     64        $n = $this->n ;
     65        $step = ($this->xdata[$n-1]-$this->xdata[0]) / ($num-1);
     66        $xnew=array();
     67        $ynew=array();
     68        $xnew[0] = $this->xdata[0];
     69        $ynew[0] = $this->ydata[0];
     70        for( $j=1; $j < $num; ++$j ) {
     71            $xnew[$j] = $xnew[0]+$j*$step;
     72            $ynew[$j] = $this->Interpolate($xnew[$j]);
     73        }
     74        return array($xnew,$ynew);
    7575    }
    7676
     
    7878    function Interpolate($xpoint) {
    7979
    80         $max = $this->n-1;
    81         $min = 0;
    82 
    83         // Binary search to find interval
    84         while( $max-$min > 1 ) {
    85             $k = ($max+$min) / 2;
    86             if( $this->xdata[$k] > $xpoint )
    87             $max=$k;
    88             else
    89             $min=$k;
    90         }
    91 
    92         // Each interval is interpolated by a 3:degree polynom function
    93         $h = $this->xdata[$max]-$this->xdata[$min];
    94 
    95         if( $h == 0  ) {
    96             JpGraphError::RaiseL(19002);
    97             //('Invalid input data for spline. Two or more consecutive input X-values are equal. Each input X-value must differ since from a mathematical point of view it must be a one-to-one mapping, i.e. each X-value must correspond to exactly one Y-value.');
    98         }
    99 
    100 
    101         $a = ($this->xdata[$max]-$xpoint)/$h;
    102         $b = ($xpoint-$this->xdata[$min])/$h;
    103         return $a*$this->ydata[$min]+$b*$this->ydata[$max]+
    104         (($a*$a*$a-$a)*$this->y2[$min]+($b*$b*$b-$b)*$this->y2[$max])*($h*$h)/6.0;
     80        $max = $this->n-1;
     81        $min = 0;
     82
     83        // Binary search to find interval
     84        while( $max-$min > 1 ) {
     85            $k = ($max+$min) / 2;
     86            if( $this->xdata[$k] > $xpoint )
     87                $max=$k;
     88            else
     89                $min=$k;
     90        }       
     91
     92        // Each interval is interpolated by a 3:degree polynom function
     93        $h = $this->xdata[$max]-$this->xdata[$min];
     94
     95        if( $h == 0  ) {
     96            JpGraphError::RaiseL(19002);
     97//('Invalid input data for spline. Two or more consecutive input X-values are equal. Each input X-value must differ since from a mathematical point of view it must be a one-to-one mapping, i.e. each X-value must correspond to exactly one Y-value.');
     98        }
     99
     100
     101        $a = ($this->xdata[$max]-$xpoint)/$h;
     102        $b = ($xpoint-$this->xdata[$min])/$h;
     103        return $a*$this->ydata[$min]+$b*$this->ydata[$max]+
     104             (($a*$a*$a-$a)*$this->y2[$min]+($b*$b*$b-$b)*$this->y2[$max])*($h*$h)/6.0;
    105105    }
    106106}
     
    111111//------------------------------------------------------------------------
    112112class Bezier {
    113     /**
    114      * @author Thomas Despoix, openXtrem company
    115      * @license released under QPL
    116      * @abstract Bezier interoplated point generation,
    117      * computed from control points data sets, based on Paul Bourke algorithm :
    118      * http://local.wasp.uwa.edu.au/~pbourke/geometry/bezier/index2.html
    119      */
     113/**
     114 * @author Thomas Despoix, openXtrem company
     115 * @license released under QPL
     116 * @abstract Bezier interoplated point generation,
     117 * computed from control points data sets, based on Paul Bourke algorithm :
     118 * http://astronomy.swin.edu.au/~pbourke/curves/bezier/
     119 */
    120120    private $datax = array();
    121121    private $datay = array();
    122122    private $n=0;
    123 
    124     function __construct($datax, $datay, $attraction_factor = 1) {
    125         // Adding control point multiple time will raise their attraction power over the curve
    126         $this->n = count($datax);
    127         if( $this->n !== count($datay) ) {
    128             JpGraphError::RaiseL(19003);
    129             //('Bezier: Number of X and Y coordinates must be the same');
    130         }
    131         $idx=0;
    132         foreach($datax as $datumx) {
    133             for ($i = 0; $i < $attraction_factor; $i++) {
    134                 $this->datax[$idx++] = $datumx;
    135             }
    136         }
    137         $idx=0;
    138         foreach($datay as $datumy) {
    139             for ($i = 0; $i < $attraction_factor; $i++) {
    140                 $this->datay[$idx++] = $datumy;
    141             }
    142         }
    143         $this->n *= $attraction_factor;
    144     }
    145 
    146     /**
    147      * Return a set of data points that specifies the bezier curve with $steps points
    148      * @param $steps Number of new points to return
    149      * @return array($datax, $datay)
    150      */
     123 
     124    function Bezier($datax, $datay, $attraction_factor = 1) {
     125        // Adding control point multiple time will raise their attraction power over the curve
     126        $this->n = count($datax);
     127        if( $this->n !== count($datay) ) {
     128            JpGraphError::RaiseL(19003);
     129//('Bezier: Number of X and Y coordinates must be the same');
     130        }
     131        $idx=0;
     132        foreach($datax as $datumx) {
     133            for ($i = 0; $i < $attraction_factor; $i++) {
     134                $this->datax[$idx++] = $datumx;
     135            }
     136        }
     137        $idx=0;
     138        foreach($datay as $datumy) {
     139            for ($i = 0; $i < $attraction_factor; $i++) {
     140                $this->datay[$idx++] = $datumy;
     141            }
     142        }
     143        $this->n *= $attraction_factor;
     144    }
     145
    151146    function Get($steps) {
    152         $datax = array();
    153         $datay = array();
    154         for ($i = 0; $i < $steps; $i++) {
    155             list($datumx, $datumy) = $this->GetPoint((double) $i / (double) $steps);
    156             $datax[$i] = $datumx;
    157             $datay[$i] = $datumy;
    158         }
    159          
    160         $datax[] = end($this->datax);
    161         $datay[] = end($this->datay);
    162          
    163         return array($datax, $datay);
    164     }
    165 
    166     /**
    167      * Return one point on the bezier curve. $mu is the position on the curve where $mu is in the
    168      * range 0 $mu < 1 where 0 is tha start point and 1 is the end point. Note that every newly computed
    169      * point depends on all the existing points
    170      *
    171      * @param $mu Position on the bezier curve
    172      * @return array($x, $y)
    173      */
     147        $datax = array();
     148        $datay = array();
     149        for ($i = 0; $i < $steps; $i++) {
     150            list($datumx, $datumy) = $this->GetPoint((double) $i / (double) $steps);       
     151            $datax[] = $datumx;
     152            $datay[] = $datumy;
     153        }
     154   
     155        $datax[] = end($this->datax);
     156        $datay[] = end($this->datay);
     157   
     158        return array($datax, $datay);
     159    }
     160 
    174161    function GetPoint($mu) {
    175         $n = $this->n - 1;
    176         $k = 0;
    177         $kn = 0;
    178         $nn = 0;
    179         $nkn = 0;
    180         $blend = 0.0;
    181         $newx = 0.0;
    182         $newy = 0.0;
    183 
    184         $muk = 1.0;
    185         $munk = (double) pow(1-$mu,(double) $n);
    186 
    187         for ($k = 0; $k <= $n; $k++) {
    188             $nn = $n;
    189             $kn = $k;
    190             $nkn = $n - $k;
    191             $blend = $muk * $munk;
    192             $muk *= $mu;
    193             $munk /= (1-$mu);
    194             while ($nn >= 1) {
    195                 $blend *= $nn;
    196                 $nn--;
    197                 if ($kn > 1) {
    198                     $blend /= (double) $kn;
    199                     $kn--;
    200                 }
    201                 if ($nkn > 1) {
    202                     $blend /= (double) $nkn;
    203                     $nkn--;
    204                 }
    205             }
    206             $newx += $this->datax[$k] * $blend;
    207             $newy += $this->datay[$k] * $blend;
    208         }
    209 
    210         return array($newx, $newy);
     162        $n = $this->n - 1;
     163        $k = 0;
     164        $kn = 0;
     165        $nn = 0;
     166        $nkn = 0;
     167        $blend = 0.0;
     168        $newx = 0.0;
     169        $newy = 0.0;
     170
     171        $muk = 1.0;
     172        $munk = (double) pow(1-$mu,(double) $n);
     173
     174        for ($k = 0; $k <= $n; $k++) {
     175            $nn = $n;
     176            $kn = $k;
     177            $nkn = $n - $k;
     178            $blend = $muk * $munk;
     179            $muk *= $mu;
     180            $munk /= (1-$mu);
     181            while ($nn >= 1) {
     182                $blend *= $nn;
     183                $nn--;
     184                if ($kn > 1) {
     185                    $blend /= (double) $kn;
     186                    $kn--;
     187                }
     188                if ($nkn > 1) {
     189                    $blend /= (double) $nkn;
     190                    $nkn--;
     191                }
     192            }
     193            $newx += $this->datax[$k] * $blend;
     194            $newy += $this->datay[$k] * $blend;
     195        }
     196
     197        return array($newx, $newy);
    211198    }
    212199}
  • trunk/client/modules/Elezioni/grafici/jpgraph_rgb.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_RGB.INC.PHP
    4 // Description: Class to handle RGb color space specification and
    5 //              named colors
    6 // Created:     2001-01-08 (Refactored to separate file 2008-08-01)
    7 // Ver:         $Id: jpgraph_rgb.inc.php 1893 2009-10-02 23:15:25Z ljp $
     3// File:        JPGRAPH_RGB.INC.PHP
     4// Description: Class to handle RGb color space specification and
     5//              named colors
     6// Created:     2001-01-08 (Refactored to separate file 2008-08-01)
     7// Ver:         $Id: jpgraph_rgb.inc.php 1049 2008-08-01 19:58:07Z ljp $
    88//
    9 // Copyright (c) Asial Corporation. All rights reserved.
     9// Copyright (c) Aditus Consulting. All rights reserved.
    1010//========================================================================
    1111
    1212
    13 /*===================================================
     13//===================================================
    1414// CLASS RGB
    1515// Description: Color definitions as RGB triples
    1616//===================================================
    17 */
    18 
    1917class RGB {
    20     public $rgb_table;
     18    public $rgb_table; 
    2119    public $img;
    2220
    23     function __construct($aImg=null) {
    24         $this->img = $aImg;
    25 
    26         // Conversion array between color names and RGB
    27         $this->rgb_table = array(
    28             'aqua'=> array(0,255,255),
    29             'lime'=> array(0,255,0),
    30             'teal'=> array(0,128,128),
    31             'whitesmoke'=>array(245,245,245),
    32             'gainsboro'=>array(220,220,220),
    33             'oldlace'=>array(253,245,230),
    34             'linen'=>array(250,240,230),
    35             'antiquewhite'=>array(250,235,215),
    36             'papayawhip'=>array(255,239,213),
    37             'blanchedalmond'=>array(255,235,205),
    38             'bisque'=>array(255,228,196),
    39             'peachpuff'=>array(255,218,185),
    40             'navajowhite'=>array(255,222,173),
    41             'moccasin'=>array(255,228,181),
    42             'cornsilk'=>array(255,248,220),
    43             'ivory'=>array(255,255,240),
    44             'lemonchiffon'=>array(255,250,205),
    45             'seashell'=>array(255,245,238),
    46             'mintcream'=>array(245,255,250),
    47             'azure'=>array(240,255,255),
    48             'aliceblue'=>array(240,248,255),
    49             'lavender'=>array(230,230,250),
    50             'lavenderblush'=>array(255,240,245),
    51             'mistyrose'=>array(255,228,225),
    52             'white'=>array(255,255,255),
    53             'black'=>array(0,0,0),
    54             'darkslategray'=>array(47,79,79),
    55             'dimgray'=>array(105,105,105),
    56             'slategray'=>array(112,128,144),
    57             'lightslategray'=>array(119,136,153),
    58             'gray'=>array(190,190,190),
    59             'lightgray'=>array(211,211,211),
    60             'midnightblue'=>array(25,25,112),
    61             'navy'=>array(0,0,128),
    62             'indigo'=>array(75,0,130),
    63             'electricindigo'=>array(102,0,255),
    64             'deepindigo'=>array(138,43,226),
    65             'pigmentindigo'=>array(75,0,130),
    66             'indigodye'=>array(0,65,106),
    67             'cornflowerblue'=>array(100,149,237),
    68             'darkslateblue'=>array(72,61,139),
    69             'slateblue'=>array(106,90,205),
    70             'mediumslateblue'=>array(123,104,238),
    71             'lightslateblue'=>array(132,112,255),
    72             'mediumblue'=>array(0,0,205),
    73             'royalblue'=>array(65,105,225),
    74             'blue'=>array(0,0,255),
    75             'dodgerblue'=>array(30,144,255),
    76             'deepskyblue'=>array(0,191,255),
    77             'skyblue'=>array(135,206,235),
    78             'lightskyblue'=>array(135,206,250),
    79             'steelblue'=>array(70,130,180),
    80             'lightred'=>array(211,167,168),
    81             'lightsteelblue'=>array(176,196,222),
    82             'lightblue'=>array(173,216,230),
    83             'powderblue'=>array(176,224,230),
    84             'paleturquoise'=>array(175,238,238),
    85             'darkturquoise'=>array(0,206,209),
    86             'mediumturquoise'=>array(72,209,204),
    87             'turquoise'=>array(64,224,208),
    88             'cyan'=>array(0,255,255),
    89             'lightcyan'=>array(224,255,255),
    90             'cadetblue'=>array(95,158,160),
    91             'mediumaquamarine'=>array(102,205,170),
    92             'aquamarine'=>array(127,255,212),
    93             'darkgreen'=>array(0,100,0),
    94             'darkolivegreen'=>array(85,107,47),
    95             'darkseagreen'=>array(143,188,143),
    96             'seagreen'=>array(46,139,87),
    97             'mediumseagreen'=>array(60,179,113),
    98             'lightseagreen'=>array(32,178,170),
    99             'palegreen'=>array(152,251,152),
    100             'springgreen'=>array(0,255,127),
    101             'lawngreen'=>array(124,252,0),
    102             'green'=>array(0,255,0),
    103             'chartreuse'=>array(127,255,0),
    104             'mediumspringgreen'=>array(0,250,154),
    105             'greenyellow'=>array(173,255,47),
    106             'limegreen'=>array(50,205,50),
    107             'yellowgreen'=>array(154,205,50),
    108             'forestgreen'=>array(34,139,34),
    109             'olivedrab'=>array(107,142,35),
    110             'darkkhaki'=>array(189,183,107),
    111             'khaki'=>array(240,230,140),
    112             'palegoldenrod'=>array(238,232,170),
    113             'lightgoldenrodyellow'=>array(250,250,210),
    114             'lightyellow'=>array(255,255,200),
    115             'yellow'=>array(255,255,0),
    116             'gold'=>array(255,215,0),
    117             'lightgoldenrod'=>array(238,221,130),
    118             'goldenrod'=>array(218,165,32),
    119             'darkgoldenrod'=>array(184,134,11),
    120             'rosybrown'=>array(188,143,143),
    121             'indianred'=>array(205,92,92),
    122             'saddlebrown'=>array(139,69,19),
    123             'sienna'=>array(160,82,45),
    124             'peru'=>array(205,133,63),
    125             'burlywood'=>array(222,184,135),
    126             'beige'=>array(245,245,220),
    127             'wheat'=>array(245,222,179),
    128             'sandybrown'=>array(244,164,96),
    129             'tan'=>array(210,180,140),
    130             'chocolate'=>array(210,105,30),
    131             'firebrick'=>array(178,34,34),
    132             'brown'=>array(165,42,42),
    133             'darksalmon'=>array(233,150,122),
    134             'salmon'=>array(250,128,114),
    135             'lightsalmon'=>array(255,160,122),
    136             'orange'=>array(255,165,0),
    137             'darkorange'=>array(255,140,0),
    138             'coral'=>array(255,127,80),
    139             'lightcoral'=>array(240,128,128),
    140             'tomato'=>array(255,99,71),
    141             'orangered'=>array(255,69,0),
    142             'red'=>array(255,0,0),
    143             'hotpink'=>array(255,105,180),
    144             'deeppink'=>array(255,20,147),
    145             'pink'=>array(255,192,203),
    146             'lightpink'=>array(255,182,193),
    147             'palevioletred'=>array(219,112,147),
    148             'maroon'=>array(176,48,96),
    149             'mediumvioletred'=>array(199,21,133),
    150             'violetred'=>array(208,32,144),
    151             'magenta'=>array(255,0,255),
    152             'violet'=>array(238,130,238),
    153             'plum'=>array(221,160,221),
    154             'orchid'=>array(218,112,214),
    155             'mediumorchid'=>array(186,85,211),
    156             'darkorchid'=>array(153,50,204),
    157             'darkviolet'=>array(148,0,211),
    158             'blueviolet'=>array(138,43,226),
    159             'purple'=>array(160,32,240),
    160             'mediumpurple'=>array(147,112,219),
    161             'thistle'=>array(216,191,216),
    162             'snow1'=>array(255,250,250),
    163             'snow2'=>array(238,233,233),
    164             'snow3'=>array(205,201,201),
    165             'snow4'=>array(139,137,137),
    166             'seashell1'=>array(255,245,238),
    167             'seashell2'=>array(238,229,222),
    168             'seashell3'=>array(205,197,191),
    169             'seashell4'=>array(139,134,130),
    170             'AntiqueWhite1'=>array(255,239,219),
    171             'AntiqueWhite2'=>array(238,223,204),
    172             'AntiqueWhite3'=>array(205,192,176),
    173             'AntiqueWhite4'=>array(139,131,120),
    174             'bisque1'=>array(255,228,196),
    175             'bisque2'=>array(238,213,183),
    176             'bisque3'=>array(205,183,158),
    177             'bisque4'=>array(139,125,107),
    178             'peachPuff1'=>array(255,218,185),
    179             'peachpuff2'=>array(238,203,173),
    180             'peachpuff3'=>array(205,175,149),
    181             'peachpuff4'=>array(139,119,101),
    182             'navajowhite1'=>array(255,222,173),
    183             'navajowhite2'=>array(238,207,161),
    184             'navajowhite3'=>array(205,179,139),
    185             'navajowhite4'=>array(139,121,94),
    186             'lemonchiffon1'=>array(255,250,205),
    187             'lemonchiffon2'=>array(238,233,191),
    188             'lemonchiffon3'=>array(205,201,165),
    189             'lemonchiffon4'=>array(139,137,112),
    190             'ivory1'=>array(255,255,240),
    191             'ivory2'=>array(238,238,224),
    192             'ivory3'=>array(205,205,193),
    193             'ivory4'=>array(139,139,131),
    194             'honeydew'=>array(193,205,193),
    195             'lavenderblush1'=>array(255,240,245),
    196             'lavenderblush2'=>array(238,224,229),
    197             'lavenderblush3'=>array(205,193,197),
    198             'lavenderblush4'=>array(139,131,134),
    199             'mistyrose1'=>array(255,228,225),
    200             'mistyrose2'=>array(238,213,210),
    201             'mistyrose3'=>array(205,183,181),
    202             'mistyrose4'=>array(139,125,123),
    203             'azure1'=>array(240,255,255),
    204             'azure2'=>array(224,238,238),
    205             'azure3'=>array(193,205,205),
    206             'azure4'=>array(131,139,139),
    207             'slateblue1'=>array(131,111,255),
    208             'slateblue2'=>array(122,103,238),
    209             'slateblue3'=>array(105,89,205),
    210             'slateblue4'=>array(71,60,139),
    211             'royalblue1'=>array(72,118,255),
    212             'royalblue2'=>array(67,110,238),
    213             'royalblue3'=>array(58,95,205),
    214             'royalblue4'=>array(39,64,139),
    215             'dodgerblue1'=>array(30,144,255),
    216             'dodgerblue2'=>array(28,134,238),
    217             'dodgerblue3'=>array(24,116,205),
    218             'dodgerblue4'=>array(16,78,139),
    219             'steelblue1'=>array(99,184,255),
    220             'steelblue2'=>array(92,172,238),
    221             'steelblue3'=>array(79,148,205),
    222             'steelblue4'=>array(54,100,139),
    223             'deepskyblue1'=>array(0,191,255),
    224             'deepskyblue2'=>array(0,178,238),
    225             'deepskyblue3'=>array(0,154,205),
    226             'deepskyblue4'=>array(0,104,139),
    227             'skyblue1'=>array(135,206,255),
    228             'skyblue2'=>array(126,192,238),
    229             'skyblue3'=>array(108,166,205),
    230             'skyblue4'=>array(74,112,139),
    231             'lightskyblue1'=>array(176,226,255),
    232             'lightskyblue2'=>array(164,211,238),
    233             'lightskyblue3'=>array(141,182,205),
    234             'lightskyblue4'=>array(96,123,139),
    235             'slategray1'=>array(198,226,255),
    236             'slategray2'=>array(185,211,238),
    237             'slategray3'=>array(159,182,205),
    238             'slategray4'=>array(108,123,139),
    239             'lightsteelblue1'=>array(202,225,255),
    240             'lightsteelblue2'=>array(188,210,238),
    241             'lightsteelblue3'=>array(162,181,205),
    242             'lightsteelblue4'=>array(110,123,139),
    243             'lightblue1'=>array(191,239,255),
    244             'lightblue2'=>array(178,223,238),
    245             'lightblue3'=>array(154,192,205),
    246             'lightblue4'=>array(104,131,139),
    247             'lightcyan1'=>array(224,255,255),
    248             'lightcyan2'=>array(209,238,238),
    249             'lightcyan3'=>array(180,205,205),
    250             'lightcyan4'=>array(122,139,139),
    251             'paleturquoise1'=>array(187,255,255),
    252             'paleturquoise2'=>array(174,238,238),
    253             'paleturquoise3'=>array(150,205,205),
    254             'paleturquoise4'=>array(102,139,139),
    255             'cadetblue1'=>array(152,245,255),
    256             'cadetblue2'=>array(142,229,238),
    257             'cadetblue3'=>array(122,197,205),
    258             'cadetblue4'=>array(83,134,139),
    259             'turquoise1'=>array(0,245,255),
    260             'turquoise2'=>array(0,229,238),
    261             'turquoise3'=>array(0,197,205),
    262             'turquoise4'=>array(0,134,139),
    263             'cyan1'=>array(0,255,255),
    264             'cyan2'=>array(0,238,238),
    265             'cyan3'=>array(0,205,205),
    266             'cyan4'=>array(0,139,139),
    267             'darkslategray1'=>array(151,255,255),
    268             'darkslategray2'=>array(141,238,238),
    269             'darkslategray3'=>array(121,205,205),
    270             'darkslategray4'=>array(82,139,139),
    271             'aquamarine1'=>array(127,255,212),
    272             'aquamarine2'=>array(118,238,198),
    273             'aquamarine3'=>array(102,205,170),
    274             'aquamarine4'=>array(69,139,116),
    275             'darkseagreen1'=>array(193,255,193),
    276             'darkseagreen2'=>array(180,238,180),
    277             'darkseagreen3'=>array(155,205,155),
    278             'darkseagreen4'=>array(105,139,105),
    279             'seagreen1'=>array(84,255,159),
    280             'seagreen2'=>array(78,238,148),
    281             'seagreen3'=>array(67,205,128),
    282             'seagreen4'=>array(46,139,87),
    283             'palegreen1'=>array(154,255,154),
    284             'palegreen2'=>array(144,238,144),
    285             'palegreen3'=>array(124,205,124),
    286             'palegreen4'=>array(84,139,84),
    287             'springgreen1'=>array(0,255,127),
    288             'springgreen2'=>array(0,238,118),
    289             'springgreen3'=>array(0,205,102),
    290             'springgreen4'=>array(0,139,69),
    291             'chartreuse1'=>array(127,255,0),
    292             'chartreuse2'=>array(118,238,0),
    293             'chartreuse3'=>array(102,205,0),
    294             'chartreuse4'=>array(69,139,0),
    295             'olivedrab1'=>array(192,255,62),
    296             'olivedrab2'=>array(179,238,58),
    297             'olivedrab3'=>array(154,205,50),
    298             'olivedrab4'=>array(105,139,34),
    299             'darkolivegreen1'=>array(202,255,112),
    300             'darkolivegreen2'=>array(188,238,104),
    301             'darkolivegreen3'=>array(162,205,90),
    302             'darkolivegreen4'=>array(110,139,61),
    303             'khaki1'=>array(255,246,143),
    304             'khaki2'=>array(238,230,133),
    305             'khaki3'=>array(205,198,115),
    306             'khaki4'=>array(139,134,78),
    307             'lightgoldenrod1'=>array(255,236,139),
    308             'lightgoldenrod2'=>array(238,220,130),
    309             'lightgoldenrod3'=>array(205,190,112),
    310             'lightgoldenrod4'=>array(139,129,76),
    311             'yellow1'=>array(255,255,0),
    312             'yellow2'=>array(238,238,0),
    313             'yellow3'=>array(205,205,0),
    314             'yellow4'=>array(139,139,0),
    315             'gold1'=>array(255,215,0),
    316             'gold2'=>array(238,201,0),
    317             'gold3'=>array(205,173,0),
    318             'gold4'=>array(139,117,0),
    319             'goldenrod1'=>array(255,193,37),
    320             'goldenrod2'=>array(238,180,34),
    321             'goldenrod3'=>array(205,155,29),
    322             'goldenrod4'=>array(139,105,20),
    323             'darkgoldenrod1'=>array(255,185,15),
    324             'darkgoldenrod2'=>array(238,173,14),
    325             'darkgoldenrod3'=>array(205,149,12),
    326             'darkgoldenrod4'=>array(139,101,8),
    327             'rosybrown1'=>array(255,193,193),
    328             'rosybrown2'=>array(238,180,180),
    329             'rosybrown3'=>array(205,155,155),
    330             'rosybrown4'=>array(139,105,105),
    331             'indianred1'=>array(255,106,106),
    332             'indianred2'=>array(238,99,99),
    333             'indianred3'=>array(205,85,85),
    334             'indianred4'=>array(139,58,58),
    335             'sienna1'=>array(255,130,71),
    336             'sienna2'=>array(238,121,66),
    337             'sienna3'=>array(205,104,57),
    338             'sienna4'=>array(139,71,38),
    339             'burlywood1'=>array(255,211,155),
    340             'burlywood2'=>array(238,197,145),
    341             'burlywood3'=>array(205,170,125),
    342             'burlywood4'=>array(139,115,85),
    343             'wheat1'=>array(255,231,186),
    344             'wheat2'=>array(238,216,174),
    345             'wheat3'=>array(205,186,150),
    346             'wheat4'=>array(139,126,102),
    347             'tan1'=>array(255,165,79),
    348             'tan2'=>array(238,154,73),
    349             'tan3'=>array(205,133,63),
    350             'tan4'=>array(139,90,43),
    351             'chocolate1'=>array(255,127,36),
    352             'chocolate2'=>array(238,118,33),
    353             'chocolate3'=>array(205,102,29),
    354             'chocolate4'=>array(139,69,19),
    355             'firebrick1'=>array(255,48,48),
    356             'firebrick2'=>array(238,44,44),
    357             'firebrick3'=>array(205,38,38),
    358             'firebrick4'=>array(139,26,26),
    359             'brown1'=>array(255,64,64),
    360             'brown2'=>array(238,59,59),
    361             'brown3'=>array(205,51,51),
    362             'brown4'=>array(139,35,35),
    363             'salmon1'=>array(255,140,105),
    364             'salmon2'=>array(238,130,98),
    365             'salmon3'=>array(205,112,84),
    366             'salmon4'=>array(139,76,57),
    367             'lightsalmon1'=>array(255,160,122),
    368             'lightsalmon2'=>array(238,149,114),
    369             'lightsalmon3'=>array(205,129,98),
    370             'lightsalmon4'=>array(139,87,66),
    371             'orange1'=>array(255,165,0),
    372             'orange2'=>array(238,154,0),
    373             'orange3'=>array(205,133,0),
    374             'orange4'=>array(139,90,0),
    375             'darkorange1'=>array(255,127,0),
    376             'darkorange2'=>array(238,118,0),
    377             'darkorange3'=>array(205,102,0),
    378             'darkorange4'=>array(139,69,0),
    379             'coral1'=>array(255,114,86),
    380             'coral2'=>array(238,106,80),
    381             'coral3'=>array(205,91,69),
    382             'coral4'=>array(139,62,47),
    383             'tomato1'=>array(255,99,71),
    384             'tomato2'=>array(238,92,66),
    385             'tomato3'=>array(205,79,57),
    386             'tomato4'=>array(139,54,38),
    387             'orangered1'=>array(255,69,0),
    388             'orangered2'=>array(238,64,0),
    389             'orangered3'=>array(205,55,0),
    390             'orangered4'=>array(139,37,0),
    391             'deeppink1'=>array(255,20,147),
    392             'deeppink2'=>array(238,18,137),
    393             'deeppink3'=>array(205,16,118),
    394             'deeppink4'=>array(139,10,80),
    395             'hotpink1'=>array(255,110,180),
    396             'hotpink2'=>array(238,106,167),
    397             'hotpink3'=>array(205,96,144),
    398             'hotpink4'=>array(139,58,98),
    399             'pink1'=>array(255,181,197),
    400             'pink2'=>array(238,169,184),
    401             'pink3'=>array(205,145,158),
    402             'pink4'=>array(139,99,108),
    403             'lightpink1'=>array(255,174,185),
    404             'lightpink2'=>array(238,162,173),
    405             'lightpink3'=>array(205,140,149),
    406             'lightpink4'=>array(139,95,101),
    407             'palevioletred1'=>array(255,130,171),
    408             'palevioletred2'=>array(238,121,159),
    409             'palevioletred3'=>array(205,104,137),
    410             'palevioletred4'=>array(139,71,93),
    411             'maroon1'=>array(255,52,179),
    412             'maroon2'=>array(238,48,167),
    413             'maroon3'=>array(205,41,144),
    414             'maroon4'=>array(139,28,98),
    415             'violetred1'=>array(255,62,150),
    416             'violetred2'=>array(238,58,140),
    417             'violetred3'=>array(205,50,120),
    418             'violetred4'=>array(139,34,82),
    419             'magenta1'=>array(255,0,255),
    420             'magenta2'=>array(238,0,238),
    421             'magenta3'=>array(205,0,205),
    422             'magenta4'=>array(139,0,139),
    423             'mediumred'=>array(140,34,34),
    424             'orchid1'=>array(255,131,250),
    425             'orchid2'=>array(238,122,233),
    426             'orchid3'=>array(205,105,201),
    427             'orchid4'=>array(139,71,137),
    428             'plum1'=>array(255,187,255),
    429             'plum2'=>array(238,174,238),
    430             'plum3'=>array(205,150,205),
    431             'plum4'=>array(139,102,139),
    432             'mediumorchid1'=>array(224,102,255),
    433             'mediumorchid2'=>array(209,95,238),
    434             'mediumorchid3'=>array(180,82,205),
    435             'mediumorchid4'=>array(122,55,139),
    436             'darkorchid1'=>array(191,62,255),
    437             'darkorchid2'=>array(178,58,238),
    438             'darkorchid3'=>array(154,50,205),
    439             'darkorchid4'=>array(104,34,139),
    440             'purple1'=>array(155,48,255),
    441             'purple2'=>array(145,44,238),
    442             'purple3'=>array(125,38,205),
    443             'purple4'=>array(85,26,139),
    444             'mediumpurple1'=>array(171,130,255),
    445             'mediumpurple2'=>array(159,121,238),
    446             'mediumpurple3'=>array(137,104,205),
    447             'mediumpurple4'=>array(93,71,139),
    448             'thistle1'=>array(255,225,255),
    449             'thistle2'=>array(238,210,238),
    450             'thistle3'=>array(205,181,205),
    451             'thistle4'=>array(139,123,139),
    452             'gray1'=>array(10,10,10),
    453             'gray2'=>array(40,40,30),
    454             'gray3'=>array(70,70,70),
    455             'gray4'=>array(100,100,100),
    456             'gray5'=>array(130,130,130),
    457             'gray6'=>array(160,160,160),
    458             'gray7'=>array(190,190,190),
    459             'gray8'=>array(210,210,210),
    460             'gray9'=>array(240,240,240),
    461             'darkgray'=>array(100,100,100),
    462             'darkblue'=>array(0,0,139),
    463             'darkcyan'=>array(0,139,139),
    464             'darkmagenta'=>array(139,0,139),
    465             'darkred'=>array(139,0,0),
    466             'silver'=>array(192, 192, 192),
    467             'eggplant'=>array(144,176,168),
    468             'lightgreen'=>array(144,238,144));
     21    function RGB($aImg=null) {
     22        $this->img = $aImg;
     23               
     24        // Conversion array between color names and RGB
     25        $this->rgb_table = array(
     26            "aqua"=> array(0,255,255),         
     27            "lime"=> array(0,255,0),           
     28            "teal"=> array(0,128,128),
     29            "whitesmoke"=>array(245,245,245),
     30            "gainsboro"=>array(220,220,220),
     31            "oldlace"=>array(253,245,230),
     32            "linen"=>array(250,240,230),
     33            "antiquewhite"=>array(250,235,215),
     34            "papayawhip"=>array(255,239,213),
     35            "blanchedalmond"=>array(255,235,205),
     36            "bisque"=>array(255,228,196),
     37            "peachpuff"=>array(255,218,185),
     38            "navajowhite"=>array(255,222,173),
     39            "moccasin"=>array(255,228,181),
     40            "cornsilk"=>array(255,248,220),
     41            "ivory"=>array(255,255,240),
     42            "lemonchiffon"=>array(255,250,205),
     43            "seashell"=>array(255,245,238),
     44            "mintcream"=>array(245,255,250),
     45            "azure"=>array(240,255,255),
     46            "aliceblue"=>array(240,248,255),
     47            "lavender"=>array(230,230,250),
     48            "lavenderblush"=>array(255,240,245),
     49            "mistyrose"=>array(255,228,225),
     50            "white"=>array(255,255,255),
     51            "black"=>array(0,0,0),
     52            "darkslategray"=>array(47,79,79),
     53            "dimgray"=>array(105,105,105),
     54            "slategray"=>array(112,128,144),
     55            "lightslategray"=>array(119,136,153),
     56            "gray"=>array(190,190,190),
     57            "lightgray"=>array(211,211,211),
     58            "midnightblue"=>array(25,25,112),
     59            "navy"=>array(0,0,128),
     60            "cornflowerblue"=>array(100,149,237),
     61            "darkslateblue"=>array(72,61,139),
     62            "slateblue"=>array(106,90,205),
     63            "mediumslateblue"=>array(123,104,238),
     64            "lightslateblue"=>array(132,112,255),
     65            "mediumblue"=>array(0,0,205),
     66            "royalblue"=>array(65,105,225),
     67            "blue"=>array(0,0,255),
     68            "dodgerblue"=>array(30,144,255),
     69            "deepskyblue"=>array(0,191,255),
     70            "skyblue"=>array(135,206,235),
     71            "lightskyblue"=>array(135,206,250),
     72            "steelblue"=>array(70,130,180),
     73            "lightred"=>array(211,167,168),
     74            "lightsteelblue"=>array(176,196,222),
     75            "lightblue"=>array(173,216,230),
     76            "powderblue"=>array(176,224,230),
     77            "paleturquoise"=>array(175,238,238),
     78            "darkturquoise"=>array(0,206,209),
     79            "mediumturquoise"=>array(72,209,204),
     80            "turquoise"=>array(64,224,208),
     81            "cyan"=>array(0,255,255),
     82            "lightcyan"=>array(224,255,255),
     83            "cadetblue"=>array(95,158,160),
     84            "mediumaquamarine"=>array(102,205,170),
     85            "aquamarine"=>array(127,255,212),
     86            "darkgreen"=>array(0,100,0),
     87            "darkolivegreen"=>array(85,107,47),
     88            "darkseagreen"=>array(143,188,143),
     89            "seagreen"=>array(46,139,87),
     90            "mediumseagreen"=>array(60,179,113),
     91            "lightseagreen"=>array(32,178,170),
     92            "palegreen"=>array(152,251,152),
     93            "springgreen"=>array(0,255,127),
     94            "lawngreen"=>array(124,252,0),
     95            "green"=>array(0,255,0),
     96            "chartreuse"=>array(127,255,0),
     97            "mediumspringgreen"=>array(0,250,154),
     98            "greenyellow"=>array(173,255,47),
     99            "limegreen"=>array(50,205,50),
     100            "yellowgreen"=>array(154,205,50),
     101            "forestgreen"=>array(34,139,34),
     102            "olivedrab"=>array(107,142,35),
     103            "darkkhaki"=>array(189,183,107),
     104            "khaki"=>array(240,230,140),
     105            "palegoldenrod"=>array(238,232,170),
     106            "lightgoldenrodyellow"=>array(250,250,210),
     107            "lightyellow"=>array(255,255,200),
     108            "yellow"=>array(255,255,0),
     109            "gold"=>array(255,215,0),
     110            "lightgoldenrod"=>array(238,221,130),
     111            "goldenrod"=>array(218,165,32),
     112            "darkgoldenrod"=>array(184,134,11),
     113            "rosybrown"=>array(188,143,143),
     114            "indianred"=>array(205,92,92),
     115            "saddlebrown"=>array(139,69,19),
     116            "sienna"=>array(160,82,45),
     117            "peru"=>array(205,133,63),
     118            "burlywood"=>array(222,184,135),
     119            "beige"=>array(245,245,220),
     120            "wheat"=>array(245,222,179),
     121            "sandybrown"=>array(244,164,96),
     122            "tan"=>array(210,180,140),
     123            "chocolate"=>array(210,105,30),
     124            "firebrick"=>array(178,34,34),
     125            "brown"=>array(165,42,42),
     126            "darksalmon"=>array(233,150,122),
     127            "salmon"=>array(250,128,114),
     128            "lightsalmon"=>array(255,160,122),
     129            "orange"=>array(255,165,0),
     130            "darkorange"=>array(255,140,0),
     131            "coral"=>array(255,127,80),
     132            "lightcoral"=>array(240,128,128),
     133            "tomato"=>array(255,99,71),
     134            "orangered"=>array(255,69,0),
     135            "red"=>array(255,0,0),
     136            "hotpink"=>array(255,105,180),
     137            "deeppink"=>array(255,20,147),
     138            "pink"=>array(255,192,203),
     139            "lightpink"=>array(255,182,193),
     140            "palevioletred"=>array(219,112,147),
     141            "maroon"=>array(176,48,96),
     142            "mediumvioletred"=>array(199,21,133),
     143            "violetred"=>array(208,32,144),
     144            "magenta"=>array(255,0,255),
     145            "violet"=>array(238,130,238),
     146            "plum"=>array(221,160,221),
     147            "orchid"=>array(218,112,214),
     148            "mediumorchid"=>array(186,85,211),
     149            "darkorchid"=>array(153,50,204),
     150            "darkviolet"=>array(148,0,211),
     151            "blueviolet"=>array(138,43,226),
     152            "purple"=>array(160,32,240),
     153            "mediumpurple"=>array(147,112,219),
     154            "thistle"=>array(216,191,216),
     155            "snow1"=>array(255,250,250),
     156            "snow2"=>array(238,233,233),
     157            "snow3"=>array(205,201,201),
     158            "snow4"=>array(139,137,137),
     159            "seashell1"=>array(255,245,238),
     160            "seashell2"=>array(238,229,222),
     161            "seashell3"=>array(205,197,191),
     162            "seashell4"=>array(139,134,130),
     163            "AntiqueWhite1"=>array(255,239,219),
     164            "AntiqueWhite2"=>array(238,223,204),
     165            "AntiqueWhite3"=>array(205,192,176),
     166            "AntiqueWhite4"=>array(139,131,120),
     167            "bisque1"=>array(255,228,196),
     168            "bisque2"=>array(238,213,183),
     169            "bisque3"=>array(205,183,158),
     170            "bisque4"=>array(139,125,107),
     171            "peachPuff1"=>array(255,218,185),
     172            "peachpuff2"=>array(238,203,173),
     173            "peachpuff3"=>array(205,175,149),
     174            "peachpuff4"=>array(139,119,101),
     175            "navajowhite1"=>array(255,222,173),
     176            "navajowhite2"=>array(238,207,161),
     177            "navajowhite3"=>array(205,179,139),
     178            "navajowhite4"=>array(139,121,94),
     179            "lemonchiffon1"=>array(255,250,205),
     180            "lemonchiffon2"=>array(238,233,191),
     181            "lemonchiffon3"=>array(205,201,165),
     182            "lemonchiffon4"=>array(139,137,112),
     183            "ivory1"=>array(255,255,240),
     184            "ivory2"=>array(238,238,224),
     185            "ivory3"=>array(205,205,193),
     186            "ivory4"=>array(139,139,131),
     187            "honeydew"=>array(193,205,193),
     188            "lavenderblush1"=>array(255,240,245),
     189            "lavenderblush2"=>array(238,224,229),
     190            "lavenderblush3"=>array(205,193,197),
     191            "lavenderblush4"=>array(139,131,134),
     192            "mistyrose1"=>array(255,228,225),
     193            "mistyrose2"=>array(238,213,210),
     194            "mistyrose3"=>array(205,183,181),
     195            "mistyrose4"=>array(139,125,123),
     196            "azure1"=>array(240,255,255),
     197            "azure2"=>array(224,238,238),
     198            "azure3"=>array(193,205,205),
     199            "azure4"=>array(131,139,139),
     200            "slateblue1"=>array(131,111,255),
     201            "slateblue2"=>array(122,103,238),
     202            "slateblue3"=>array(105,89,205),
     203            "slateblue4"=>array(71,60,139),
     204            "royalblue1"=>array(72,118,255),
     205            "royalblue2"=>array(67,110,238),
     206            "royalblue3"=>array(58,95,205),
     207            "royalblue4"=>array(39,64,139),
     208            "dodgerblue1"=>array(30,144,255),
     209            "dodgerblue2"=>array(28,134,238),
     210            "dodgerblue3"=>array(24,116,205),
     211            "dodgerblue4"=>array(16,78,139),
     212            "steelblue1"=>array(99,184,255),
     213            "steelblue2"=>array(92,172,238),
     214            "steelblue3"=>array(79,148,205),
     215            "steelblue4"=>array(54,100,139),
     216            "deepskyblue1"=>array(0,191,255),
     217            "deepskyblue2"=>array(0,178,238),
     218            "deepskyblue3"=>array(0,154,205),
     219            "deepskyblue4"=>array(0,104,139),
     220            "skyblue1"=>array(135,206,255),
     221            "skyblue2"=>array(126,192,238),
     222            "skyblue3"=>array(108,166,205),
     223            "skyblue4"=>array(74,112,139),
     224            "lightskyblue1"=>array(176,226,255),
     225            "lightskyblue2"=>array(164,211,238),
     226            "lightskyblue3"=>array(141,182,205),
     227            "lightskyblue4"=>array(96,123,139),
     228            "slategray1"=>array(198,226,255),
     229            "slategray2"=>array(185,211,238),
     230            "slategray3"=>array(159,182,205),
     231            "slategray4"=>array(108,123,139),
     232            "lightsteelblue1"=>array(202,225,255),
     233            "lightsteelblue2"=>array(188,210,238),
     234            "lightsteelblue3"=>array(162,181,205),
     235            "lightsteelblue4"=>array(110,123,139),
     236            "lightblue1"=>array(191,239,255),
     237            "lightblue2"=>array(178,223,238),
     238            "lightblue3"=>array(154,192,205),
     239            "lightblue4"=>array(104,131,139),
     240            "lightcyan1"=>array(224,255,255),
     241            "lightcyan2"=>array(209,238,238),
     242            "lightcyan3"=>array(180,205,205),
     243            "lightcyan4"=>array(122,139,139),
     244            "paleturquoise1"=>array(187,255,255),
     245            "paleturquoise2"=>array(174,238,238),
     246            "paleturquoise3"=>array(150,205,205),
     247            "paleturquoise4"=>array(102,139,139),
     248            "cadetblue1"=>array(152,245,255),
     249            "cadetblue2"=>array(142,229,238),
     250            "cadetblue3"=>array(122,197,205),
     251            "cadetblue4"=>array(83,134,139),
     252            "turquoise1"=>array(0,245,255),
     253            "turquoise2"=>array(0,229,238),
     254            "turquoise3"=>array(0,197,205),
     255            "turquoise4"=>array(0,134,139),
     256            "cyan1"=>array(0,255,255),
     257            "cyan2"=>array(0,238,238),
     258            "cyan3"=>array(0,205,205),
     259            "cyan4"=>array(0,139,139),
     260            "darkslategray1"=>array(151,255,255),
     261            "darkslategray2"=>array(141,238,238),
     262            "darkslategray3"=>array(121,205,205),
     263            "darkslategray4"=>array(82,139,139),
     264            "aquamarine1"=>array(127,255,212),
     265            "aquamarine2"=>array(118,238,198),
     266            "aquamarine3"=>array(102,205,170),
     267            "aquamarine4"=>array(69,139,116),
     268            "darkseagreen1"=>array(193,255,193),
     269            "darkseagreen2"=>array(180,238,180),
     270            "darkseagreen3"=>array(155,205,155),
     271            "darkseagreen4"=>array(105,139,105),
     272            "seagreen1"=>array(84,255,159),
     273            "seagreen2"=>array(78,238,148),
     274            "seagreen3"=>array(67,205,128),
     275            "seagreen4"=>array(46,139,87),
     276            "palegreen1"=>array(154,255,154),
     277            "palegreen2"=>array(144,238,144),
     278            "palegreen3"=>array(124,205,124),
     279            "palegreen4"=>array(84,139,84),
     280            "springgreen1"=>array(0,255,127),
     281            "springgreen2"=>array(0,238,118),
     282            "springgreen3"=>array(0,205,102),
     283            "springgreen4"=>array(0,139,69),
     284            "chartreuse1"=>array(127,255,0),
     285            "chartreuse2"=>array(118,238,0),
     286            "chartreuse3"=>array(102,205,0),
     287            "chartreuse4"=>array(69,139,0),
     288            "olivedrab1"=>array(192,255,62),
     289            "olivedrab2"=>array(179,238,58),
     290            "olivedrab3"=>array(154,205,50),
     291            "olivedrab4"=>array(105,139,34),
     292            "darkolivegreen1"=>array(202,255,112),
     293            "darkolivegreen2"=>array(188,238,104),
     294            "darkolivegreen3"=>array(162,205,90),
     295            "darkolivegreen4"=>array(110,139,61),
     296            "khaki1"=>array(255,246,143),
     297            "khaki2"=>array(238,230,133),
     298            "khaki3"=>array(205,198,115),
     299            "khaki4"=>array(139,134,78),
     300            "lightgoldenrod1"=>array(255,236,139),
     301            "lightgoldenrod2"=>array(238,220,130),
     302            "lightgoldenrod3"=>array(205,190,112),
     303            "lightgoldenrod4"=>array(139,129,76),
     304            "yellow1"=>array(255,255,0),
     305            "yellow2"=>array(238,238,0),
     306            "yellow3"=>array(205,205,0),
     307            "yellow4"=>array(139,139,0),
     308            "gold1"=>array(255,215,0),
     309            "gold2"=>array(238,201,0),
     310            "gold3"=>array(205,173,0),
     311            "gold4"=>array(139,117,0),
     312            "goldenrod1"=>array(255,193,37),
     313            "goldenrod2"=>array(238,180,34),
     314            "goldenrod3"=>array(205,155,29),
     315            "goldenrod4"=>array(139,105,20),
     316            "darkgoldenrod1"=>array(255,185,15),
     317            "darkgoldenrod2"=>array(238,173,14),
     318            "darkgoldenrod3"=>array(205,149,12),
     319            "darkgoldenrod4"=>array(139,101,8),
     320            "rosybrown1"=>array(255,193,193),
     321            "rosybrown2"=>array(238,180,180),
     322            "rosybrown3"=>array(205,155,155),
     323            "rosybrown4"=>array(139,105,105),
     324            "indianred1"=>array(255,106,106),
     325            "indianred2"=>array(238,99,99),
     326            "indianred3"=>array(205,85,85),
     327            "indianred4"=>array(139,58,58),
     328            "sienna1"=>array(255,130,71),
     329            "sienna2"=>array(238,121,66),
     330            "sienna3"=>array(205,104,57),
     331            "sienna4"=>array(139,71,38),
     332            "burlywood1"=>array(255,211,155),
     333            "burlywood2"=>array(238,197,145),
     334            "burlywood3"=>array(205,170,125),
     335            "burlywood4"=>array(139,115,85),
     336            "wheat1"=>array(255,231,186),
     337            "wheat2"=>array(238,216,174),
     338            "wheat3"=>array(205,186,150),
     339            "wheat4"=>array(139,126,102),
     340            "tan1"=>array(255,165,79),
     341            "tan2"=>array(238,154,73),
     342            "tan3"=>array(205,133,63),
     343            "tan4"=>array(139,90,43),
     344            "chocolate1"=>array(255,127,36),
     345            "chocolate2"=>array(238,118,33),
     346            "chocolate3"=>array(205,102,29),
     347            "chocolate4"=>array(139,69,19),
     348            "firebrick1"=>array(255,48,48),
     349            "firebrick2"=>array(238,44,44),
     350            "firebrick3"=>array(205,38,38),
     351            "firebrick4"=>array(139,26,26),
     352            "brown1"=>array(255,64,64),
     353            "brown2"=>array(238,59,59),
     354            "brown3"=>array(205,51,51),
     355            "brown4"=>array(139,35,35),
     356            "salmon1"=>array(255,140,105),
     357            "salmon2"=>array(238,130,98),
     358            "salmon3"=>array(205,112,84),
     359            "salmon4"=>array(139,76,57),
     360            "lightsalmon1"=>array(255,160,122),
     361            "lightsalmon2"=>array(238,149,114),
     362            "lightsalmon3"=>array(205,129,98),
     363            "lightsalmon4"=>array(139,87,66),
     364            "orange1"=>array(255,165,0),
     365            "orange2"=>array(238,154,0),
     366            "orange3"=>array(205,133,0),
     367            "orange4"=>array(139,90,0),
     368            "darkorange1"=>array(255,127,0),
     369            "darkorange2"=>array(238,118,0),
     370            "darkorange3"=>array(205,102,0),
     371            "darkorange4"=>array(139,69,0),
     372            "coral1"=>array(255,114,86),
     373            "coral2"=>array(238,106,80),
     374            "coral3"=>array(205,91,69),
     375            "coral4"=>array(139,62,47),
     376            "tomato1"=>array(255,99,71),
     377            "tomato2"=>array(238,92,66),
     378            "tomato3"=>array(205,79,57),
     379            "tomato4"=>array(139,54,38),
     380            "orangered1"=>array(255,69,0),
     381            "orangered2"=>array(238,64,0),
     382            "orangered3"=>array(205,55,0),
     383            "orangered4"=>array(139,37,0),
     384            "deeppink1"=>array(255,20,147),
     385            "deeppink2"=>array(238,18,137),
     386            "deeppink3"=>array(205,16,118),
     387            "deeppink4"=>array(139,10,80),
     388            "hotpink1"=>array(255,110,180),
     389            "hotpink2"=>array(238,106,167),
     390            "hotpink3"=>array(205,96,144),
     391            "hotpink4"=>array(139,58,98),
     392            "pink1"=>array(255,181,197),
     393            "pink2"=>array(238,169,184),
     394            "pink3"=>array(205,145,158),
     395            "pink4"=>array(139,99,108),
     396            "lightpink1"=>array(255,174,185),
     397            "lightpink2"=>array(238,162,173),
     398            "lightpink3"=>array(205,140,149),
     399            "lightpink4"=>array(139,95,101),
     400            "palevioletred1"=>array(255,130,171),
     401            "palevioletred2"=>array(238,121,159),
     402            "palevioletred3"=>array(205,104,137),
     403            "palevioletred4"=>array(139,71,93),
     404            "maroon1"=>array(255,52,179),
     405            "maroon2"=>array(238,48,167),
     406            "maroon3"=>array(205,41,144),
     407            "maroon4"=>array(139,28,98),
     408            "violetred1"=>array(255,62,150),
     409            "violetred2"=>array(238,58,140),
     410            "violetred3"=>array(205,50,120),
     411            "violetred4"=>array(139,34,82),
     412            "magenta1"=>array(255,0,255),
     413            "magenta2"=>array(238,0,238),
     414            "magenta3"=>array(205,0,205),
     415            "magenta4"=>array(139,0,139),
     416            "mediumred"=>array(140,34,34),         
     417            "orchid1"=>array(255,131,250),
     418            "orchid2"=>array(238,122,233),
     419            "orchid3"=>array(205,105,201),
     420            "orchid4"=>array(139,71,137),
     421            "plum1"=>array(255,187,255),
     422            "plum2"=>array(238,174,238),
     423            "plum3"=>array(205,150,205),
     424            "plum4"=>array(139,102,139),
     425            "mediumorchid1"=>array(224,102,255),
     426            "mediumorchid2"=>array(209,95,238),
     427            "mediumorchid3"=>array(180,82,205),
     428            "mediumorchid4"=>array(122,55,139),
     429            "darkorchid1"=>array(191,62,255),
     430            "darkorchid2"=>array(178,58,238),
     431            "darkorchid3"=>array(154,50,205),
     432            "darkorchid4"=>array(104,34,139),
     433            "purple1"=>array(155,48,255),
     434            "purple2"=>array(145,44,238),
     435            "purple3"=>array(125,38,205),
     436            "purple4"=>array(85,26,139),
     437            "mediumpurple1"=>array(171,130,255),
     438            "mediumpurple2"=>array(159,121,238),
     439            "mediumpurple3"=>array(137,104,205),
     440            "mediumpurple4"=>array(93,71,139),
     441            "thistle1"=>array(255,225,255),
     442            "thistle2"=>array(238,210,238),
     443            "thistle3"=>array(205,181,205),
     444            "thistle4"=>array(139,123,139),
     445            "gray1"=>array(10,10,10),
     446            "gray2"=>array(40,40,30),
     447            "gray3"=>array(70,70,70),
     448            "gray4"=>array(100,100,100),
     449            "gray5"=>array(130,130,130),
     450            "gray6"=>array(160,160,160),
     451            "gray7"=>array(190,190,190),
     452            "gray8"=>array(210,210,210),
     453            "gray9"=>array(240,240,240),
     454            "darkgray"=>array(100,100,100),
     455            "darkblue"=>array(0,0,139),
     456            "darkcyan"=>array(0,139,139),
     457            "darkmagenta"=>array(139,0,139),
     458            "darkred"=>array(139,0,0),
     459            "silver"=>array(192, 192, 192),
     460            "eggplant"=>array(144,176,168),
     461            "lightgreen"=>array(144,238,144));         
    469462    }
    470 
    471 
    472     //----------------
    473     // PUBLIC METHODS
     463//----------------
     464// PUBLIC METHODS
    474465    // Colors can be specified as either
    475     // 1. #xxxxxx   HTML style
    476     // 2. "colorname"  as a named color
    477     // 3. array(r,g,b) RGB triple
    478     // This function translates this to a native RGB format and returns an
     466    // 1. #xxxxxx                       HTML style
     467    // 2. "colorname"   as a named color
     468    // 3. array(r,g,b)  RGB triple
     469    // This function translates this to a native RGB format and returns an 
    479470    // RGB triple.
    480 
    481471    function Color($aColor) {
    482         if (is_string($aColor)) {
    483             $matches = array();
    484             // this regex will parse a color string and fill the $matches array as such:
    485             // 0: the full match if any
    486             // 1: a hex string preceded by a hash, can be 3 characters (#fff) or 6 (#ffffff) (4 or 5 also accepted but...)
    487             // 2,3,4: r,g,b values in hex if the first character of the string is #
    488             // 5: all alpha-numeric characters at the beginning of the string if string does not start with #
    489             // 6: alpha value prefixed by @ if supplied
    490             // 7: alpha value with @ stripped
    491             // 8: adjust value prefixed with : if supplied
    492             // 9: adjust value with : stripped
    493             $regex = '/(#([0-9a-fA-F]{1,2})([0-9a-fA-F]{1,2})([0-9a-fA-F]{1,2}))?([\w]+)?(@([\d\.,]+))?(:([\d\.,]+))?/';
    494             if(!preg_match($regex, $aColor, $matches)) {
    495                 JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor");
    496             }
    497             if(empty($matches[5])) {
    498                 $r = strlen($matches[2]) == 1 ? $matches[2].$matches[2] : $matches[2];
    499                 $g = strlen($matches[3]) == 1 ? $matches[3].$matches[3] : $matches[3];
    500                 $b = strlen($matches[4]) == 1 ? $matches[4].$matches[4] : $matches[4];
    501                 $r = hexdec($r);
    502                 $g = hexdec($g);
    503                 $b = hexdec($b);
    504             }else {
    505                 if(!isset($this->rgb_table[$matches[5]]) ) {
    506                     JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor");
    507                 }
    508                 $r = $this->rgb_table[$matches[5]][0];
    509                 $g = $this->rgb_table[$matches[5]][1];
    510                 $b = $this->rgb_table[$matches[5]][2];
    511             }
    512             $alpha      = isset($matches[7]) ? str_replace(',','.',$matches[7]) : 0;
    513             $adj        = isset($matches[9]) ? str_replace(',','.',$matches[9]) : 1.0;
    514 
    515             if( $adj < 0 ) {
    516                 JpGraphError::RaiseL(25077);//('Adjustment factor for color must be > 0');
    517             }
    518 
    519             // Scale adj so that an adj=2 always
    520             // makes the color 100% white (i.e. 255,255,255.
    521             // and adj=1 neutral and adj=0 black.
    522             if( $adj == 1) {
    523                 return array($r,$g,$b,$alpha);
    524             }
    525             elseif( $adj > 1 ) {
    526                 $m = ($adj-1.0)*(255-min(255,min($r,min($g,$b))));
    527                 return array(min(255,$r+$m), min(255,$g+$m), min(255,$b+$m),$alpha);
    528             }
    529             elseif( $adj < 1 ) {
    530                 $m = ($adj-1.0)*max(255,max($r,max($g,$b)));
    531                 return array(max(0,$r+$m), max(0,$g+$m), max(0,$b+$m),$alpha);
    532             }
    533         } elseif( is_array($aColor) ) {
    534             if(!isset($aColor[3])) $aColor[3] = 0;
    535             return $aColor;
    536         }
    537         else {
    538             JpGraphError::RaiseL(25079,$aColor,count($aColor));//(" Unknown color specification: $aColor , size=".count($aColor));
    539         }
     472        if (is_string($aColor)) {
     473            // Strip of any alpha factor
     474            $pos = strpos($aColor,'@');
     475            if( $pos === false ) {
     476                $alpha = 0;
     477            }
     478            else {
     479                $pos2 = strpos($aColor,':');
     480                if( $pos2===false )
     481                    $pos2 = $pos-1; // Sentinel
     482                if( $pos > $pos2 ) {
     483                    $alpha = str_replace(',','.',substr($aColor,$pos+1));
     484                    $aColor = substr($aColor,0,$pos);
     485                }
     486                else {
     487                    $alpha = substr($aColor,$pos+1,$pos2-$pos-1);
     488                    $aColor = substr($aColor,0,$pos).substr($aColor,$pos2);
     489                }
     490            }
     491
     492            // Extract potential adjustment figure at end of color
     493            // specification
     494            $pos = strpos($aColor,":");
     495            if( $pos === false ) {
     496                $adj = 1.0;
     497            }
     498            else {
     499                $adj = 0.0 + str_replace(',','.',substr($aColor,$pos+1));
     500                $aColor = substr($aColor,0,$pos);
     501            }
     502            if( $adj < 0 )
     503                JpGraphError::RaiseL(25077);//('Adjustment factor for color must be > 0');
     504
     505            if (substr($aColor, 0, 1) == "#") {
     506                $r = hexdec(substr($aColor, 1, 2));
     507                $g = hexdec(substr($aColor, 3, 2));
     508                $b = hexdec(substr($aColor, 5, 2));
     509            } else {
     510                if(!isset($this->rgb_table[$aColor]) )
     511                    JpGraphError::RaiseL(25078,$aColor);//(" Unknown color: $aColor");
     512                $tmp=$this->rgb_table[$aColor];
     513                $r = $tmp[0];
     514                $g = $tmp[1];
     515                $b = $tmp[2];
     516            }
     517            // Scale adj so that an adj=2 always
     518            // makes the color 100% white (i.e. 255,255,255.
     519            // and adj=1 neutral and adj=0 black.
     520            if( $adj > 1 ) {
     521                $m = ($adj-1.0)*(255-min(255,min($r,min($g,$b))));
     522                return array(min(255,$r+$m), min(255,$g+$m), min(255,$b+$m),$alpha);
     523            }
     524            elseif( $adj < 1 ) {
     525                $m = ($adj-1.0)*max(255,max($r,max($g,$b)));
     526                return array(max(0,$r+$m), max(0,$g+$m), max(0,$b+$m),$alpha);
     527            }
     528            else {
     529                return array($r,$g,$b,$alpha);
     530            }
     531
     532        } elseif( is_array($aColor) ) {
     533            if( count($aColor)==3 ) {
     534                $aColor[3]=0;
     535                return $aColor;
     536            }
     537            else
     538                return $aColor;
     539        }
     540        else
     541            JpGraphError::RaiseL(25079,$aColor,count($aColor));//(" Unknown color specification: $aColor , size=".count($aColor));
    540542    }
    541 
     543       
    542544    // Compare two colors
    543545    // return true if equal
    544546    function Equal($aCol1,$aCol2) {
    545         $c1 = $this->Color($aCol1);
    546         $c2 = $this->Color($aCol2);
    547         return $c1[0]==$c2[0] && $c1[1]==$c2[1] && $c1[2]==$c2[2] ;
     547        $c1 = $this->Color($aCol1);
     548        $c2 = $this->Color($aCol2);
     549        if( $c1[0]==$c2[0] && $c1[1]==$c2[1] && $c1[2]==$c2[2] )
     550            return true;
     551        else
     552            return false;
    548553    }
    549 
     554       
    550555    // Allocate a new color in the current image
    551556    // Return new color index, -1 if no more colors could be allocated
    552557    function Allocate($aColor,$aAlpha=0.0) {
    553         list ($r, $g, $b, $a) = $this->color($aColor);
    554         // If alpha is specified in the color string then this
    555         // takes precedence over the second argument
    556         if( $a > 0 ) {
    557             $aAlpha = $a;
    558         }
    559         if( $aAlpha < 0 || $aAlpha > 1 ) {
    560             JpGraphError::RaiseL(25080);//('Alpha parameter for color must be between 0.0 and 1.0');
    561         }
    562         return imagecolorresolvealpha($this->img, $r, $g, $b, round($aAlpha * 127));
     558        list ($r, $g, $b, $a) = $this->color($aColor);
     559        // If alpha is specified in the color string then this
     560        // takes precedence over the second argument
     561        if( $a > 0 )
     562            $aAlpha = $a;
     563        if( $aAlpha < 0 || $aAlpha > 1 ) {
     564            JpGraphError::RaiseL(25080);//('Alpha parameter for color must be between 0.0 and 1.0');
     565        }
     566        return imagecolorresolvealpha($this->img, $r, $g, $b, round($aAlpha * 127));
    563567    }
    564 
    565     // Try to convert an array with three valid numbers to the corresponding hex array
    566     // This is currenly only used in processing the colors for barplots in order to be able
    567     // to handle the case where the color might be specified as an array of colros as well.
    568     // In that case we must be able to find out if an array of values should be interpretated as
    569     // a single color (specifeid as an RGB triple)
    570     static function tryHexConversion($aColor) {
    571         if( is_array( $aColor ) ) {
    572             if( count( $aColor ) == 3 ) {
    573                 if( is_numeric($aColor[0]) && is_numeric($aColor[1]) && is_numeric($aColor[2]) ) {
    574                     if( ($aColor[0] >= 0 && $aColor[0] <= 255) &&
    575                         ($aColor[1] >= 0 && $aColor[1] <= 255) &&
    576                         ($aColor[2] >= 0 && $aColor[2] <= 255) ) {
    577                         return sprintf('#%02x%02x%02x',$aColor[0],$aColor[1],$aColor[2]);
    578                     }
    579                 }
    580             }
    581         }
    582         return $aColor;
    583     }
    584 
    585     // Return a RGB tripple corresponding to a position in the normal light spectrum
    586     // The argumen values is in the range [0, 1] where a value of 0 correponds to blue and
    587     // a value of 1 corresponds to red. Values in betwen is mapped to a linear interpolation
    588     // of the constituting colors in the visible color spectra.
    589     // The $aDynamicRange specified how much of the dynamic range we shold use
    590     // a value of 1.0 give the full dyanmic range and a lower value give more dark
    591     // colors. In the extreme of 0.0 then all colors will be black.
    592     static function GetSpectrum($aVal,$aDynamicRange=1.0) {
    593         if( $aVal < 0 || $aVal > 1.0001 ) {
    594             return array(0,0,0); // Invalid case - just return black
    595         }
    596 
    597         $sat = round(255*$aDynamicRange);
    598         $a = 0.25;
    599         if( $aVal <= 0.25 ) {
    600             return array(0, round($sat*$aVal/$a), $sat);
    601         }
    602         elseif( $aVal <= 0.5 ) {
    603             return array(0, $sat, round($sat-$sat*($aVal-0.25)/$a));
    604         }
    605         elseif( $aVal <= 0.75 ) {
    606             return array(round($sat*($aVal-0.5)/$a), $sat, 0);
    607         }
    608         else {
    609             return array($sat, round($sat-$sat*($aVal-0.75)/$a), 0);
    610         }
    611     }
    612 
    613568} // Class
    614569
  • trunk/client/modules/Elezioni/grafici/jpgraph_scatter.php

    r265 r267  
    1 <?php
     1<?php 
    22/*=======================================================================
    3  // File:        JPGRAPH_SCATTER.PHP
    4  // Description: Scatter (and impuls) plot extension for JpGraph
    5  // Created:     2001-02-11
    6  // Ver:         $Id: jpgraph_scatter.php 1397 2009-06-27 21:34:14Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_SCATTER.PHP
     4// Description: Scatter (and impuls) plot extension for JpGraph
     5// Created:     2001-02-11
     6// Ver:         $Id: jpgraph_scatter.php 957 2007-12-01 14:00:29Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111require_once ('jpgraph_plotmark.inc.php');
    1212
     
    2020    public $iArrowSize = 2;
    2121    private $isizespec = array(
    22         array(2,1),array(3,2),array(4,3),array(6,4),array(7,4),array(8,5),array(10,6),array(12,7),array(16,8),array(20,10)
    23         );
    24     function __construct() {
    25         // Empty
     22        array(2,1),array(3,2),array(4,3),array(6,4),array(7,4),array(8,5),array(10,6),array(12,7),array(16,8),array(20,10));
     23    function FieldArrow() {
    2624    }
    2725
    2826    function SetSize($aSize,$aArrowSize=2) {
    29         $this->iSize = $aSize;
    30         $this->iArrowSize = $aArrowSize;
     27        $this->iSize = $aSize;
     28        $this->iArrowSize = $aArrowSize;
    3129    }
    3230
    3331    function SetColor($aColor) {
    34         $this->iColor = $aColor;
     32        $this->iColor = $aColor;
    3533    }
    3634
    3735    function Stroke($aImg,$x,$y,$a) {
    38         // First rotate the center coordinates
    39         list($x,$y) = $aImg->Rotate($x,$y);
    40 
    41         $old_origin = $aImg->SetCenter($x,$y);
    42         $old_a = $aImg->a;
    43         $aImg->SetAngle(-$a+$old_a);
    44 
    45         $dx = round($this->iSize/2);
    46         $c = array($x-$dx,$y,$x+$dx,$y);
    47         $x += $dx;
    48 
    49         list($dx,$dy) = $this->isizespec[$this->iArrowSize];
    50         $ca = array($x,$y,$x-$dx,$y-$dy,$x-$dx,$y+$dy,$x,$y);
    51 
    52         $aImg->SetColor($this->iColor);
    53         $aImg->Polygon($c);
    54         $aImg->FilledPolygon($ca);
    55 
    56         $aImg->SetCenter($old_origin[0],$old_origin[1]);
    57         $aImg->SetAngle($old_a);
     36        // First rotate the center coordinates
     37        list($x,$y) = $aImg->Rotate($x,$y);
     38
     39        $old_origin = $aImg->SetCenter($x,$y);
     40        $old_a = $aImg->a;
     41        $aImg->SetAngle(-$a+$old_a);
     42
     43        $dx = round($this->iSize/2);
     44        $c = array($x-$dx,$y,$x+$dx,$y);
     45        $x += $dx;
     46
     47        list($dx,$dy) = $this->isizespec[$this->iArrowSize];
     48        $ca = array($x,$y,$x-$dx,$y-$dy,$x-$dx,$y+$dy,$x,$y);
     49
     50        $aImg->SetColor($this->iColor);
     51        $aImg->Polygon($c);
     52        $aImg->FilledPolygon($ca);
     53
     54        $aImg->SetCenter($old_origin[0],$old_origin[1]);
     55        $aImg->SetAngle($old_a);
    5856    }
    5957}
     
    6765    private $iAngles = array();
    6866    private $iCallback = '';
    69 
    70     function __construct($datay,$datax,$angles) {
    71         if( (count($datax) != count($datay)) )
    72         JpGraphError::RaiseL(20001);//("Fieldplots must have equal number of X and Y points.");
    73         if( (count($datax) != count($angles)) )
    74         JpGraphError::RaiseL(20002);//("Fieldplots must have an angle specified for each X and Y points.");
    75 
    76         $this->iAngles = $angles;
    77 
    78         parent::__construct($datay,$datax);
    79         $this->value->SetAlign('center','center');
    80         $this->value->SetMargin(15);
    81 
    82         $this->arrow = new FieldArrow();
     67   
     68    function FieldPlot($datay,$datax,$angles) {
     69        if( (count($datax) != count($datay)) )
     70            JpGraphError::RaiseL(20001);//("Fieldplots must have equal number of X and Y points.");
     71        if( (count($datax) != count($angles)) )
     72            JpGraphError::RaiseL(20002);//("Fieldplots must have an angle specified for each X and Y points.");
     73       
     74        $this->iAngles = $angles;
     75
     76        $this->Plot($datay,$datax);
     77        $this->value->SetAlign('center','center');
     78        $this->value->SetMargin(15);
     79
     80        $this->arrow = new FieldArrow();
    8381    }
    8482
    8583    function SetCallback($aFunc) {
    86         $this->iCallback = $aFunc;
     84        $this->iCallback = $aFunc;
    8785    }
    8886
    8987    function Stroke($img,$xscale,$yscale) {
    9088
    91         // Remeber base color and size
    92         $bc = $this->arrow->iColor;
    93         $bs = $this->arrow->iSize;
    94         $bas = $this->arrow->iArrowSize;
    95 
    96         for( $i=0; $i<$this->numpoints; ++$i ) {
    97             // Skip null values
    98             if( $this->coords[0][$i]==="" )
    99             continue;
    100 
    101             $f = $this->iCallback;
    102             if( $f != "" ) {
    103                 list($cc,$cs,$cas) = call_user_func($f,$this->coords[1][$i],$this->coords[0][$i],$this->iAngles[$i]);
    104                 // Fall back on global data if the callback isn't set
    105                 if( $cc  == "" ) $cc = $bc;
    106                 if( $cs  == "" ) $cs = $bs;
    107                 if( $cas == "" ) $cas = $bas;
    108                 $this->arrow->SetColor($cc);
    109                 $this->arrow->SetSize($cs,$cas);
    110             }
    111 
    112             $xt = $xscale->Translate($this->coords[1][$i]);
    113             $yt = $yscale->Translate($this->coords[0][$i]);
    114 
    115             $this->arrow->Stroke($img,$xt,$yt,$this->iAngles[$i]);
    116             $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt);
    117         }
    118     }
    119 
     89        // Remeber base color and size
     90        $bc = $this->arrow->iColor;
     91        $bs = $this->arrow->iSize;
     92        $bas = $this->arrow->iArrowSize;
     93
     94        for( $i=0; $i<$this->numpoints; ++$i ) {
     95            // Skip null values
     96            if( $this->coords[0][$i]==="" )
     97                continue;
     98
     99            $f = $this->iCallback;
     100            if( $f != "" ) {
     101                list($cc,$cs,$cas) = call_user_func($f,$this->coords[1][$i],$this->coords[0][$i],$this->iAngles[$i]);
     102                // Fall back on global data if the callback isn't set
     103                if( $cc  == "" ) $cc = $bc;
     104                if( $cs  == "" ) $cs = $bs;
     105                if( $cas == "" ) $cas = $bas;
     106                $this->arrow->SetColor($cc);       
     107                $this->arrow->SetSize($cs,$cas);
     108            }
     109
     110            $xt = $xscale->Translate($this->coords[1][$i]);
     111            $yt = $yscale->Translate($this->coords[0][$i]);     
     112
     113            $this->arrow->Stroke($img,$xt,$yt,$this->iAngles[$i]);
     114            $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt);
     115        }
     116    }
     117       
    120118    // Framework function
    121119    function Legend($aGraph) {
    122         if( $this->legend != "" ) {
    123             $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0,
    124             $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    125         }
    126     }
     120        if( $this->legend != "" ) {
     121            $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0,
     122                                $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     123        }
     124    }   
    127125}
    128126
     
    132130//===================================================
    133131class ScatterPlot extends Plot {
    134     public $mark,$link;
     132    public $mark = '';
    135133    private $impuls = false;
    136     //---------------
    137     // CONSTRUCTOR
    138     function __construct($datay,$datax=false) {
    139         if( is_array($datax) && (count($datax) != count($datay)) ) {
    140                 JpGraphError::RaiseL(20003);//("Scatterplot must have equal number of X and Y points.");
    141         }
    142         parent::__construct($datay,$datax);
    143         $this->mark = new PlotMark();
    144         $this->mark->SetType(MARK_SQUARE);
    145         $this->mark->SetColor($this->color);
    146         $this->value->SetAlign('center','center');
    147         $this->value->SetMargin(0);
    148         $this->link = new LineProperty(1,'black','solid');
    149         $this->link->iShow = false;
    150     }
    151 
    152     //---------------
    153     // PUBLIC METHODS
     134    private $linkpoints = false, $linkpointweight=1, $linkpointcolor="black";
     135//---------------
     136// CONSTRUCTOR
     137    function ScatterPlot($datay,$datax=false) {
     138        if( (count($datax) != count($datay)) && is_array($datax))
     139            JpGraphError::RaiseL(20003);//("Scatterplot must have equal number of X and Y points.");
     140        $this->Plot($datay,$datax);
     141        $this->mark = new PlotMark();
     142        $this->mark->SetType(MARK_SQUARE);
     143        $this->mark->SetColor($this->color);
     144        $this->value->SetAlign('center','center');
     145        $this->value->SetMargin(0);
     146    }
     147
     148//---------------
     149// PUBLIC METHODS       
    154150    function SetImpuls($f=true) {
    155         $this->impuls = $f;
    156     }
    157 
    158     function SetStem($f=true) {
    159         $this->impuls = $f;
    160     }
     151        $this->impuls = $f;
     152    }   
    161153
    162154    // Combine the scatter plot points with a line
    163     function SetLinkPoints($aFlag=true,$aColor="black",$aWeight=1,$aStyle='solid') {
    164         $this->link->iShow = $aFlag;
    165         $this->link->iColor = $aColor;
    166         $this->link->iWeight = $aWeight;
    167         $this->link->iStyle = $aStyle;
     155    function SetLinkPoints($aFlag=true,$aColor="black",$aWeight=1) {
     156        $this->linkpoints=$aFlag;
     157        $this->linkpointcolor=$aColor;
     158        $this->linkpointweight=$aWeight;
    168159    }
    169160
    170161    function Stroke($img,$xscale,$yscale) {
    171162
    172         $ymin=$yscale->scale_abs[0];
    173         if( $yscale->scale[0] < 0 )
    174         $yzero=$yscale->Translate(0);
    175         else
    176         $yzero=$yscale->scale_abs[0];
    177 
    178         $this->csimareas = '';
    179         for( $i=0; $i<$this->numpoints; ++$i ) {
    180 
    181             // Skip null values
    182             if( $this->coords[0][$i]==='' || $this->coords[0][$i]==='-' || $this->coords[0][$i]==='x')
    183             continue;
    184 
    185             if( isset($this->coords[1]) )
    186             $xt = $xscale->Translate($this->coords[1][$i]);
    187             else
    188             $xt = $xscale->Translate($i);
    189             $yt = $yscale->Translate($this->coords[0][$i]);
    190 
    191 
    192             if( $this->link->iShow && isset($yt_old) ) {
    193                 $img->SetColor($this->link->iColor);
    194                 $img->SetLineWeight($this->link->iWeight);
    195                 $old = $img->SetLineStyle($this->link->iStyle);
    196                 $img->StyleLine($xt_old,$yt_old,$xt,$yt);
    197                 $img->SetLineStyle($old);
    198             }
    199 
    200             if( $this->impuls ) {
    201                 $img->SetColor($this->color);
    202                 $img->SetLineWeight($this->weight);
    203                 $img->Line($xt,$yzero,$xt,$yt);
    204             }
    205 
    206             if( !empty($this->csimtargets[$i]) ) {
    207                 if( !empty($this->csimwintargets[$i]) ) {
    208                     $this->mark->SetCSIMTarget($this->csimtargets[$i],$this->csimwintargets[$i]);
    209                 }
    210                 else {
    211                     $this->mark->SetCSIMTarget($this->csimtargets[$i]);
    212                 }
    213                 $this->mark->SetCSIMAlt($this->csimalts[$i]);
    214             }
    215 
    216             if( isset($this->coords[1]) ) {
    217                 $this->mark->SetCSIMAltVal($this->coords[0][$i],$this->coords[1][$i]);
    218             }
    219             else {
    220                 $this->mark->SetCSIMAltVal($this->coords[0][$i],$i);
    221             }
    222 
    223             $this->mark->Stroke($img,$xt,$yt);
    224 
    225             $this->csimareas .= $this->mark->GetCSIMAreas();
    226             $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt);
    227 
    228             $xt_old = $xt;
    229             $yt_old = $yt;
    230         }
    231     }
    232 
     163        $ymin=$yscale->scale_abs[0];
     164        if( $yscale->scale[0] < 0 )
     165            $yzero=$yscale->Translate(0);
     166        else
     167            $yzero=$yscale->scale_abs[0];
     168           
     169        $this->csimareas = '';
     170        for( $i=0; $i<$this->numpoints; ++$i ) {
     171
     172            // Skip null values
     173            if( $this->coords[0][$i]==='' || $this->coords[0][$i]==='-' || $this->coords[0][$i]==='x')
     174                continue;
     175
     176            if( isset($this->coords[1]) )
     177                $xt = $xscale->Translate($this->coords[1][$i]);
     178            else
     179                $xt = $xscale->Translate($i);
     180            $yt = $yscale->Translate($this->coords[0][$i]);     
     181
     182
     183            if( $this->linkpoints && isset($yt_old) ) {
     184                $img->SetColor($this->linkpointcolor);
     185                $img->SetLineWeight($this->linkpointweight);
     186                $img->Line($xt_old,$yt_old,$xt,$yt);
     187            }
     188
     189            if( $this->impuls ) {
     190                $img->SetColor($this->color);
     191                $img->SetLineWeight($this->weight);
     192                $img->Line($xt,$yzero,$xt,$yt);
     193            }
     194       
     195            if( !empty($this->csimtargets[$i]) ) {
     196                if( !empty($this->csimwintargets[$i]) ) {
     197                    $this->mark->SetCSIMTarget($this->csimtargets[$i],$this->csimwintargets[$i]);
     198                }
     199                else {
     200                    $this->mark->SetCSIMTarget($this->csimtargets[$i]);
     201                }
     202                $this->mark->SetCSIMAlt($this->csimalts[$i]);
     203            }
     204           
     205            if( isset($this->coords[1]) ) {
     206                $this->mark->SetCSIMAltVal($this->coords[0][$i],$this->coords[1][$i]);
     207            }
     208            else {
     209                $this->mark->SetCSIMAltVal($this->coords[0][$i],$i);
     210            }
     211
     212            $this->mark->Stroke($img,$xt,$yt);
     213       
     214            $this->csimareas .= $this->mark->GetCSIMAreas();
     215            $this->value->Stroke($img,$this->coords[0][$i],$xt,$yt);
     216
     217            $xt_old = $xt;
     218            $yt_old = $yt;
     219        }
     220    }
     221       
    233222    // Framework function
    234223    function Legend($aGraph) {
    235         if( $this->legend != "" ) {
    236             $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0,
    237             $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
    238         }
    239     }
     224        if( $this->legend != "" ) {
     225            $aGraph->legend->Add($this->legend,$this->mark->fill_color,$this->mark,0,
     226                                $this->legendcsimtarget,$this->legendcsimalt,$this->legendcsimwintarget);
     227        }
     228    }   
    240229} // Class
    241230/* EOF */
  • trunk/client/modules/Elezioni/grafici/jpgraph_stock.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_STOCK.PHP
    4  // Description: Stock plot extension for JpGraph
    5  // Created:     2003-01-27
    6  // Ver:         $Id: jpgraph_stock.php 1364 2009-06-24 07:07:44Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_STOCK.PHP
     4// Description: Stock plot extension for JpGraph
     5// Created:     2003-01-27
     6// Ver:         $Id: jpgraph_stock.php 957 2007-12-01 14:00:29Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212//===================================================
     
    1818    private $iEndLines=1;
    1919    private $iStockColor1='white',$iStockColor2='darkred',$iStockColor3='darkred';
    20     //---------------
    21     // CONSTRUCTOR
    22     function __construct($datay,$datax=false) {
    23         if( count($datay) % $this->iTupleSize ) {
    24             JpGraphError::RaiseL(21001,$this->iTupleSize);
    25             //('Data values for Stock charts must contain an even multiple of '.$this->iTupleSize.' data points.');
    26         }
    27         parent::__construct($datay,$datax);
    28         $this->numpoints /= $this->iTupleSize;
     20//---------------
     21// CONSTRUCTOR
     22    function StockPlot($datay,$datax=false) {
     23        if( count($datay) % $this->iTupleSize ) {
     24            JpGraphError::RaiseL(21001,$this->iTupleSize);
     25//('Data values for Stock charts must contain an even multiple of '.$this->iTupleSize.' data points.');
     26        }
     27        $this->Plot($datay,$datax);
     28        $this->numpoints /= $this->iTupleSize;
    2929    }
    30     //---------------
    31     // PUBLIC METHODS
    32 
     30//---------------
     31// PUBLIC METHODS
     32       
    3333    function SetColor($aColor,$aColor1='white',$aColor2='darkred',$aColor3='darkred') {
    34         $this->color = $aColor;
    35         $this->iStockColor1 = $aColor1;
    36         $this->iStockColor2 = $aColor2;
    37         $this->iStockColor3 = $aColor3;
     34        $this->color = $aColor;
     35        $this->iStockColor1 = $aColor1;
     36        $this->iStockColor2 = $aColor2;
     37        $this->iStockColor3 = $aColor3;
    3838    }
    3939
    4040    function SetWidth($aWidth) {
    41         // Make sure it's odd
    42         $this->iWidth = 2*floor($aWidth/2)+1;
     41        // Make sure it's odd
     42        $this->iWidth = 2*floor($aWidth/2)+1;
    4343    }
    4444
    4545    function HideEndLines($aHide=true) {
    46         $this->iEndLines = !$aHide;
     46        $this->iEndLines = !$aHide;
    4747    }
    4848
    4949    // Gets called before any axis are stroked
    5050    function PreStrokeAdjust($graph) {
    51         if( $this->center ) {
    52             $a=0.5; $b=0.5;
    53             $this->numpoints++;
    54         } else {
    55             $a=0; $b=0;
    56         }
    57         $graph->xaxis->scale->ticks->SetXLabelOffset($a);
    58         $graph->SetTextScaleOff($b);
     51        if( $this->center ) {
     52            $a=0.5; $b=0.5;
     53            $this->numpoints++;
     54        } else {
     55            $a=0; $b=0;
     56        }
     57        $graph->xaxis->scale->ticks->SetXLabelOffset($a);
     58        $graph->SetTextScaleOff($b);                                           
    5959    }
    60 
     60       
    6161    // Method description
    6262    function Stroke($img,$xscale,$yscale) {
    63         $n=$this->numpoints;
    64         if( $this->center ) $n--;
    65         if( isset($this->coords[1]) ) {
    66             if( count($this->coords[1])!=$n ) {
    67                 JpGraphError::RaiseL(2003,count($this->coords[1]),$n);
    68                 // ("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints");
    69             }
    70             else {
    71                 $exist_x = true;
    72             }
    73         }
    74         else {
    75             $exist_x = false;
    76         }
     63        $n=$this->numpoints;
     64        if( $this->center ) $n--;
     65        if( isset($this->coords[1]) ) {
     66            if( count($this->coords[1])!=$n )
     67                JpGraphError::RaiseL(2003,count($this->coords[1]),$n);
     68//("Number of X and Y points are not equal. Number of X-points:".count($this->coords[1])." Number of Y-points:$numpoints");
     69            else
     70                $exist_x = true;
     71        }
     72        else
     73            $exist_x = false;
    7774
    78         if( $exist_x ) {
    79             $xs=$this->coords[1][0];
    80         }
    81         else {
    82             $xs=0;
    83         }
     75        if( $exist_x )
     76            $xs=$this->coords[1][0];
     77        else
     78            $xs=0;
     79               
     80        $ts = $this->iTupleSize;
     81        $this->csimareas = '';
     82        for( $i=0; $i<$n; ++$i) {
    8483
    85         $ts = $this->iTupleSize;
    86         $this->csimareas = '';
    87         for( $i=0; $i<$n; ++$i) {
     84            //If value is NULL, then don't draw a bar at all
     85            if ($this->coords[0][$i] === null) continue;
    8886
    89             //If value is NULL, then don't draw a bar at all
    90             if ($this->coords[0][$i*$ts] === null) continue;
     87            if( $exist_x ) $x=$this->coords[1][$i];
     88            else $x=$i;
     89            $xt = $xscale->Translate($x);
     90           
     91            $neg = $this->coords[0][$i*$ts] > $this->coords[0][$i*$ts+1] ;
     92            $yopen  = $yscale->Translate($this->coords[0][$i*$ts]);
     93            $yclose = $yscale->Translate($this->coords[0][$i*$ts+1]);
     94            $ymin   = $yscale->Translate($this->coords[0][$i*$ts+2]);
     95            $ymax   = $yscale->Translate($this->coords[0][$i*$ts+3]);
    9196
    92             if( $exist_x ) {
    93                 $x=$this->coords[1][$i];
    94                                 if ($x === null) continue;
    95             }
    96             else {
    97                 $x=$i;
    98             }
    99             $xt = $xscale->Translate($x);
     97            $dx = floor($this->iWidth/2);
     98            $xl = $xt - $dx;
     99            $xr = $xt + $dx;
    100100
    101             $neg = $this->coords[0][$i*$ts] > $this->coords[0][$i*$ts+1] ;
    102             $yopen  = $yscale->Translate($this->coords[0][$i*$ts]);
    103             $yclose = $yscale->Translate($this->coords[0][$i*$ts+1]);
    104             $ymin   = $yscale->Translate($this->coords[0][$i*$ts+2]);
    105             $ymax   = $yscale->Translate($this->coords[0][$i*$ts+3]);
     101            if( $neg )
     102                $img->SetColor($this->iStockColor3);
     103            else
     104                $img->SetColor($this->iStockColor1);
     105            $img->FilledRectangle($xl,$yopen,$xr,$yclose);
     106            $img->SetLineWeight($this->weight);
     107            if( $neg )
     108                $img->SetColor($this->iStockColor2);
     109            else
     110                $img->SetColor($this->color);
     111       
     112            $img->Rectangle($xl,$yopen,$xr,$yclose);
    106113
    107             $dx = floor($this->iWidth/2);
    108             $xl = $xt - $dx;
    109             $xr = $xt + $dx;
     114            if( $yopen < $yclose ) {
     115                $ytop = $yopen ;
     116                $ybottom = $yclose ;
     117            }
     118            else {
     119                $ytop = $yclose ;
     120                $ybottom = $yopen ;
     121            }
     122            $img->SetColor($this->color);
     123            $img->Line($xt,$ytop,$xt,$ymax);
     124            $img->Line($xt,$ybottom,$xt,$ymin);
    110125
    111             if( $neg ) {
    112                 $img->SetColor($this->iStockColor3);
    113             }
    114             else {
    115                 $img->SetColor($this->iStockColor1);
    116             }
    117             $img->FilledRectangle($xl,$yopen,$xr,$yclose);
    118             $img->SetLineWeight($this->weight);
    119             if( $neg ) {
    120                 $img->SetColor($this->iStockColor2);
    121             }
    122             else {
    123                 $img->SetColor($this->color);
    124             }
     126            if( $this->iEndLines ) {
     127                $img->Line($xl,$ymax,$xr,$ymax);
     128                $img->Line($xl,$ymin,$xr,$ymin);
     129            }
    125130
    126             $img->Rectangle($xl,$yopen,$xr,$yclose);
     131            // A chance for subclasses to add things to the bar
     132            // for data point i
     133            $this->ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg);
    127134
    128             if( $yopen < $yclose ) {
    129                 $ytop = $yopen ;
    130                 $ybottom = $yclose ;
    131             }
    132             else {
    133                 $ytop = $yclose ;
    134                 $ybottom = $yopen ;
    135             }
    136             $img->SetColor($this->color);
    137             $img->Line($xt,$ytop,$xt,$ymax);
    138             $img->Line($xt,$ybottom,$xt,$ymin);
    139 
    140             if( $this->iEndLines ) {
    141                 $img->Line($xl,$ymax,$xr,$ymax);
    142                 $img->Line($xl,$ymin,$xr,$ymin);
    143             }
    144 
    145             // A chance for subclasses to add things to the bar
    146             // for data point i
    147             $this->ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg);
    148 
    149             // Setup image maps
    150             if( !empty($this->csimtargets[$i]) ) {
    151                 $this->csimareas.= '<area shape="rect" coords="'.
    152                 round($xl).','.round($ytop).','.
    153                 round($xr).','.round($ybottom).'" ';
    154                 $this->csimareas .= ' href="'.$this->csimtargets[$i].'"';
    155                 if( !empty($this->csimalts[$i]) ) {
    156                     $sval=$this->csimalts[$i];
    157                     $this->csimareas .= " title=\"$sval\" alt=\"$sval\" ";
    158                 }
    159                 $this->csimareas.= "  />\n";
    160             }
    161         }
    162         return true;
     135            // Setup image maps
     136            if( !empty($this->csimtargets[$i]) ) {
     137                $this->csimareas.= '<area shape="rect" coords="'.
     138                    round($xl).','.round($ytop).','.
     139                    round($xr).','.round($ybottom).'" ';   
     140                $this->csimareas .= ' href="'.$this->csimtargets[$i].'"';
     141                if( !empty($this->csimalts[$i]) ) {
     142                    $sval=$this->csimalts[$i];
     143                    $this->csimareas .= " title=\"$sval\" alt=\"$sval\" ";
     144                }
     145                $this->csimareas.= "  />\n";
     146            }
     147        }                       
     148        return true;
    163149    }
    164150
     
    173159class BoxPlot extends StockPlot {
    174160    private $iPColor='black',$iNColor='white';
    175 
    176     function __construct($datay,$datax=false) {
    177         $this->iTupleSize=5;
    178         parent::__construct($datay,$datax);
     161    function BoxPlot($datay,$datax=false) {
     162        $this->iTupleSize=5;
     163        parent::StockPlot($datay,$datax);
    179164    }
    180165
    181166    function SetMedianColor($aPos,$aNeg) {
    182         $this->iPColor = $aPos;
    183         $this->iNColor = $aNeg;
     167        $this->iPColor = $aPos;
     168        $this->iNColor = $aNeg;
    184169    }
    185170
    186171    function ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg) {
    187         if( $neg )
    188         $img->SetColor($this->iNColor);
    189         else
    190         $img->SetColor($this->iPColor);
    191 
    192         $y = $yscale->Translate($this->coords[0][$i*5+4]);
    193         $img->Line($xl,$y,$xr,$y);
     172        if( $neg )
     173            $img->SetColor($this->iNColor);
     174        else
     175            $img->SetColor($this->iPColor);
     176       
     177        $y = $yscale->Translate($this->coords[0][$i*5+4]);
     178        $img->Line($xl,$y,$xr,$y);
    194179    }
    195180}
  • trunk/client/modules/Elezioni/grafici/jpgraph_text.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        JPGRAPH_TEXT.INC.PHP
    4 // Description: Class to handle text as object in the graph.
    5 //              The low level text layout engine is handled by the GD class
    6 // Created:     2001-01-08 (Refactored to separate file 2008-08-01)
    7 // Ver:         $Id: jpgraph_text.inc.php 1844 2009-09-26 17:05:31Z ljp $
     3// File:        JPGRAPH_TEXT.INC.PHP
     4// Description: Class to handle text as object in the graph.
     5//              The low level text layout engine is handled by the GD class
     6// Created:     2001-01-08 (Refactored to separate file 2008-08-01)
     7// Ver:         $Id: jpgraph_text.inc.php 1048 2008-08-01 19:56:46Z ljp $
    88//
    9 // Copyright (c) Asial Corporation. All rights reserved.
     9// Copyright (c) Aditus Consulting. All rights reserved.
    1010//========================================================================
    1111
     
    1616//===================================================
    1717class Text {
    18     public $t;
     18    public $t,$margin=0;
    1919    public $x=0,$y=0,$halign="left",$valign="top",$color=array(0,0,0);
    2020    public $hide=false, $dir=0;
    2121    public $iScalePosY=null,$iScalePosX=null;
    2222    public $iWordwrap=0;
    23     public $font_family=FF_DEFAULT,$font_style=FS_NORMAL; // old. FF_FONT1
    24     protected $boxed=false; // Should the text be boxed
     23    public $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12;
     24    protected $boxed=false;     // Should the text be boxed
    2525    protected $paragraph_align="left";
    2626    protected $icornerradius=0,$ishadowwidth=3;
    2727    protected $fcolor='white',$bcolor='black',$shadow=false;
    2828    protected $iCSIMarea='',$iCSIMalt='',$iCSIMtarget='',$iCSIMWinTarget='';
    29     private $iBoxType = 1; // Which variant of filled box around text we want
    30 
    31     // for __get, __set
    32     private $_margin;
    33     private $_font_size=8; // old. 12
    34 
    35     //---------------
    36     // CONSTRUCTOR
     29
     30//---------------
     31// CONSTRUCTOR
    3732
    3833    // Create new text at absolute pixel coordinates
    39     function __construct($aTxt="",$aXAbsPos=0,$aYAbsPos=0) {
    40         if( ! is_string($aTxt) ) {
    41             JpGraphError::RaiseL(25050);//('First argument to Text::Text() must be s atring.');
    42         }
    43         $this->t = $aTxt;
    44         $this->x = round($aXAbsPos);
    45         $this->y = round($aYAbsPos);
    46         $this->margin = 0;
    47     }
    48     //---------------
    49     // PUBLIC METHODS
     34    function Text($aTxt="",$aXAbsPos=0,$aYAbsPos=0) {
     35        if( ! is_string($aTxt) ) {
     36            JpGraphError::RaiseL(25050);//('First argument to Text::Text() must be s atring.');
     37        }
     38        $this->t = $aTxt;
     39        $this->x = round($aXAbsPos);
     40        $this->y = round($aYAbsPos);
     41        $this->margin = 0;
     42    }
     43//---------------
     44// PUBLIC METHODS       
    5045    // Set the string in the text object
    5146    function Set($aTxt) {
    52         $this->t = $aTxt;
    53     }
    54 
     47        $this->t = $aTxt;
     48    }
     49       
    5550    // Alias for Pos()
    5651    function SetPos($aXAbsPos=0,$aYAbsPos=0,$aHAlign="left",$aVAlign="top") {
    57     //$this->Pos($aXAbsPos,$aYAbsPos,$aHAlign,$aVAlign);
    58         $this->x = $aXAbsPos;
    59         $this->y = $aYAbsPos;
    60         $this->halign = $aHAlign;
    61         $this->valign = $aVAlign;
     52        //$this->Pos($aXAbsPos,$aYAbsPos,$aHAlign,$aVAlign);
     53        $this->x = $aXAbsPos;
     54        $this->y = $aYAbsPos;
     55        $this->halign = $aHAlign;
     56        $this->valign = $aVAlign;
    6257    }
    6358
    6459    function SetScalePos($aX,$aY) {
    65         $this->iScalePosX = $aX;
    66         $this->iScalePosY = $aY;
    67     }
    68 
     60        $this->iScalePosX = $aX;
     61        $this->iScalePosY = $aY;
     62    }
     63       
    6964    // Specify alignment for the text
    7065    function Align($aHAlign,$aVAlign="top",$aParagraphAlign="") {
    71         $this->halign = $aHAlign;
    72         $this->valign = $aVAlign;
    73         if( $aParagraphAlign != "" )
    74             $this->paragraph_align = $aParagraphAlign;
    75     }
    76 
     66        $this->halign = $aHAlign;
     67        $this->valign = $aVAlign;
     68        if( $aParagraphAlign != "" )
     69            $this->paragraph_align = $aParagraphAlign;
     70    }           
     71   
    7772    // Alias
    7873    function SetAlign($aHAlign,$aVAlign="top",$aParagraphAlign="") {
    79         $this->Align($aHAlign,$aVAlign,$aParagraphAlign);
     74        $this->Align($aHAlign,$aVAlign,$aParagraphAlign);
    8075    }
    8176
    8277    // Specifies the alignment for a multi line text
    8378    function ParagraphAlign($aAlign) {
    84         $this->paragraph_align = $aAlign;
     79        $this->paragraph_align = $aAlign;
    8580    }
    8681
    8782    // Specifies the alignment for a multi line text
    8883    function SetParagraphAlign($aAlign) {
    89         $this->paragraph_align = $aAlign;
     84        $this->paragraph_align = $aAlign;
    9085    }
    9186
    9287    function SetShadow($aShadowColor='gray',$aShadowWidth=3) {
    93         $this->ishadowwidth=$aShadowWidth;
    94         $this->shadow=$aShadowColor;
    95         $this->boxed=true;
     88        $this->ishadowwidth=$aShadowWidth;
     89        $this->shadow=$aShadowColor;
     90        $this->boxed=true;
    9691    }
    9792
    9893    function SetWordWrap($aCol) {
    99         $this->iWordwrap = $aCol ;
    100     }
    101 
     94        $this->iWordwrap = $aCol ;
     95    }
     96       
    10297    // Specify that the text should be boxed. fcolor=frame color, bcolor=border color,
    10398    // $shadow=drop shadow should be added around the text.
    10499    function SetBox($aFrameColor=array(255,255,255),$aBorderColor=array(0,0,0),$aShadowColor=false,$aCornerRadius=4,$aShadowWidth=3) {
    105         if( $aFrameColor === false ) {
    106             $this->boxed=false;
    107         }
    108         else {
    109             $this->boxed=true;
    110         }
    111         $this->fcolor=$aFrameColor;
    112         $this->bcolor=$aBorderColor;
    113         // For backwards compatibility when shadow was just true or false
    114         if( $aShadowColor === true ) {
    115             $aShadowColor = 'gray';
    116         }
    117         $this->shadow=$aShadowColor;
    118         $this->icornerradius=$aCornerRadius;
    119         $this->ishadowwidth=$aShadowWidth;
    120     }
    121 
    122     function SetBox2($aFrameColor=array(255,255,255),$aBorderColor=array(0,0,0),$aShadowColor=false,$aCornerRadius=4,$aShadowWidth=3) {
    123         $this->iBoxType=2;
    124         $this->SetBox($aFrameColor,$aBorderColor,$aShadowColor,$aCornerRadius,$aShadowWidth);
    125     }
    126 
     100        if( $aFrameColor==false )
     101            $this->boxed=false;
     102        else
     103            $this->boxed=true;
     104        $this->fcolor=$aFrameColor;
     105        $this->bcolor=$aBorderColor;
     106        // For backwards compatibility when shadow was just true or false
     107        if( $aShadowColor === true )
     108            $aShadowColor = 'gray';
     109        $this->shadow=$aShadowColor;
     110        $this->icornerradius=$aCornerRadius;
     111        $this->ishadowwidth=$aShadowWidth;
     112    }
     113       
    127114    // Hide the text
    128115    function Hide($aHide=true) {
    129         $this->hide=$aHide;
    130     }
    131 
    132     // This looks ugly since it's not a very orthogonal design
     116        $this->hide=$aHide;
     117    }
     118       
     119    // This looks ugly since it's not a very orthogonal design 
    133120    // but I added this "inverse" of Hide() to harmonize
    134     // with some classes which I designed more recently (especially)
     121    // with some classes which I designed more recently (especially) 
    135122    // jpgraph_gantt
    136123    function Show($aShow=true) {
    137         $this->hide=!$aShow;
    138     }
    139 
     124        $this->hide=!$aShow;
     125    }
     126       
    140127    // Specify font
    141128    function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) {
    142         $this->font_family=$aFamily;
    143         $this->font_style=$aStyle;
    144         $this->font_size=$aSize;
    145     }
    146 
     129        $this->font_family=$aFamily;
     130        $this->font_style=$aStyle;
     131        $this->font_size=$aSize;
     132    }
     133                       
    147134    // Center the text between $left and $right coordinates
    148135    function Center($aLeft,$aRight,$aYAbsPos=false) {
    149         $this->x = $aLeft + ($aRight-$aLeft )/2;
    150         $this->halign = "center";
    151         if( is_numeric($aYAbsPos) )
    152             $this->y = $aYAbsPos;
    153     }
    154 
     136        $this->x = $aLeft + ($aRight-$aLeft     )/2;
     137        $this->halign = "center";
     138        if( is_numeric($aYAbsPos) )
     139            $this->y = $aYAbsPos;               
     140    }
     141       
    155142    // Set text color
    156143    function SetColor($aColor) {
    157         $this->color = $aColor;
    158     }
    159 
     144        $this->color = $aColor;
     145    }
     146       
    160147    function SetAngle($aAngle) {
    161         $this->SetOrientation($aAngle);
    162     }
    163 
     148        $this->SetOrientation($aAngle);
     149    }
     150       
    164151    // Orientation of text. Note only TTF fonts can have an arbitrary angle
    165152    function SetOrientation($aDirection=0) {
    166         if( is_numeric($aDirection) )
    167             $this->dir=$aDirection;
    168         elseif( $aDirection=="h" )
    169             $this->dir = 0;
    170         elseif( $aDirection=="v" )
    171             $this->dir = 90;
    172         else
    173             JpGraphError::RaiseL(25051);//(" Invalid direction specified for text.");
    174     }
    175 
     153        if( is_numeric($aDirection) )
     154            $this->dir=$aDirection;     
     155        elseif( $aDirection=="h" )
     156            $this->dir = 0;
     157        elseif( $aDirection=="v" )
     158            $this->dir = 90;
     159        else JpGraphError::RaiseL(25051);//(" Invalid direction specified for text.");
     160    }
     161       
    176162    // Total width of text
    177163    function GetWidth($aImg) {
    178         $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size);
    179         $w = $aImg->GetTextWidth($this->t,$this->dir);
    180         return $w;
    181     }
    182 
     164        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
     165        $w = $aImg->GetTextWidth($this->t,$this->dir);
     166        return $w;     
     167    }
     168       
    183169    // Hight of font
    184170    function GetFontHeight($aImg) {
    185         $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size);
    186         $h = $aImg->GetFontHeight();
    187         return $h;
     171        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
     172        $h = $aImg->GetFontHeight();
     173        return $h;
    188174
    189175    }
    190176
    191177    function GetTextHeight($aImg) {
    192         $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size);
    193         $h = $aImg->GetTextHeight($this->t,$this->dir);
    194         return $h;
     178        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); 
     179        $h = $aImg->GetTextHeight($this->t,$this->dir);
     180        return $h;
    195181    }
    196182
    197183    function GetHeight($aImg) {
    198     // Synonym for GetTextHeight()
    199         $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size);
    200         $h = $aImg->GetTextHeight($this->t,$this->dir);
    201         return $h;
     184        // Synonym for GetTextHeight()
     185        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); 
     186        $h = $aImg->GetTextHeight($this->t,$this->dir);
     187        return $h;
    202188    }
    203189
     
    205191    // on the context.
    206192    function SetMargin($aMarg) {
    207         $this->margin = $aMarg;
     193        $this->margin = $aMarg;
    208194    }
    209195
    210196    function StrokeWithScale($aImg,$axscale,$ayscale) {
    211         if( $this->iScalePosX === null || $this->iScalePosY === null ) {
    212             $this->Stroke($aImg);
    213         }
    214         else {
    215             $this->Stroke($aImg,
    216                 round($axscale->Translate($this->iScalePosX)),
    217                 round($ayscale->Translate($this->iScalePosY)));
    218         }
     197        if( $this->iScalePosX === null ||
     198            $this->iScalePosY === null ) {
     199            $this->Stroke($aImg);
     200        }
     201        else {
     202            $this->Stroke($aImg,
     203                          round($axscale->Translate($this->iScalePosX)),
     204                          round($ayscale->Translate($this->iScalePosY)));
     205        }
    219206    }
    220207
    221208    function SetCSIMTarget($aURITarget,$aAlt='',$aWinTarget='') {
    222         $this->iCSIMtarget = $aURITarget;
    223         $this->iCSIMalt = $aAlt;
    224         $this->iCSIMWinTarget = $aWinTarget;
     209        $this->iCSIMtarget = $aURITarget;
     210        $this->iCSIMalt = $aAlt;
     211        $this->iCSIMWinTarget = $aWinTarget;
    225212    }
    226213
    227214    function GetCSIMareas() {
    228         if( $this->iCSIMtarget !== '' ) {
    229             return $this->iCSIMarea;
    230         }
    231         else {
    232             return '';
    233         }
     215        if( $this->iCSIMtarget !== '' )
     216            return $this->iCSIMarea;
     217        else
     218            return '';
    234219    }
    235220
     
    237222    function Stroke($aImg,$x=null,$y=null) {
    238223
    239         if( $x !== null ) $this->x = round($x);
    240         if( $y !== null ) $this->y = round($y);
    241 
    242         // Insert newlines
    243         if( $this->iWordwrap > 0 ) {
    244             $this->t = wordwrap($this->t,$this->iWordwrap,"\n");
    245         }
    246 
    247         // If position been given as a fraction of the image size
    248         // calculate the absolute position
    249         if( $this->x < 1 && $this->x > 0 ) $this->x *= $aImg->width;
    250         if( $this->y < 1 && $this->y > 0 ) $this->y *= $aImg->height;
    251 
    252         $aImg->PushColor($this->color);
    253         $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size);
    254         $aImg->SetTextAlign($this->halign,$this->valign);
    255 
    256         if( $this->boxed ) {
    257             if( $this->fcolor=="nofill" ) {
    258                 $this->fcolor=false;
    259             }
    260 
    261             $oldweight=$aImg->SetLineWeight(1);
    262 
    263             if( $this->iBoxType == 2 && $this->font_family > FF_FONT2+2 ) {
    264 
    265                 $bbox = $aImg->StrokeBoxedText2($this->x, $this->y,
    266                                                 $this->t, $this->dir,
    267                                                 $this->fcolor,
    268                                                 $this->bcolor,
    269                                                 $this->shadow,
    270                                                 $this->paragraph_align,
    271                                                 2,4,
    272                                                 $this->icornerradius,
    273                                                 $this->ishadowwidth);
    274             }
    275             else {
    276                 $bbox = $aImg->StrokeBoxedText($this->x,$this->y,$this->t,
    277                     $this->dir,$this->fcolor,$this->bcolor,$this->shadow,
    278                     $this->paragraph_align,3,3,$this->icornerradius,
    279                     $this->ishadowwidth);
    280             }
    281 
    282             $aImg->SetLineWeight($oldweight);
    283         }
    284         else {
    285             $debug=false;
    286             $bbox = $aImg->StrokeText($this->x,$this->y,$this->t,$this->dir,$this->paragraph_align,$debug);
    287         }
    288 
    289         // Create CSIM targets
    290         $coords = $bbox[0].','.$bbox[1].','.$bbox[2].','.$bbox[3].','.$bbox[4].','.$bbox[5].','.$bbox[6].','.$bbox[7];
    291         $this->iCSIMarea = "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($this->iCSIMtarget)."\" ";
    292         if( trim($this->iCSIMalt) != '' ) {
    293             $this->iCSIMarea .= " alt=\"".$this->iCSIMalt."\" ";
    294             $this->iCSIMarea .= " title=\"".$this->iCSIMalt."\" ";
    295         }
    296         if( trim($this->iCSIMWinTarget) != '' ) {
    297             $this->iCSIMarea .= " target=\"".$this->iCSIMWinTarget."\" ";
    298         }
    299         $this->iCSIMarea .= " />\n";
    300 
    301         $aImg->PopColor($this->color);
    302     }
    303 
    304     function __get($name) {
    305 
    306         if (strpos($name, 'raw_') !== false) {
    307             // if $name == 'raw_left_margin' , return $this->_left_margin;
    308             $variable_name = '_' . str_replace('raw_', '', $name);
    309             return $this->$variable_name;
    310         }
    311 
    312         $variable_name = '_' . $name;
    313 
    314         if (isset($this->$variable_name)) {
    315             return $this->$variable_name * SUPERSAMPLING_SCALE;
    316         } else {
    317             JpGraphError::RaiseL('25132', $name);
    318         }
    319     }
    320 
    321     function __set($name, $value) {
    322         $this->{'_'.$name} = $value;
     224        if( !empty($x) ) $this->x = round($x);
     225        if( !empty($y) ) $this->y = round($y);
     226
     227        // Insert newlines
     228        if( $this->iWordwrap > 0 ) {
     229            $this->t = wordwrap($this->t,$this->iWordwrap,"\n");
     230        }
     231
     232        // If position been given as a fraction of the image size
     233        // calculate the absolute position
     234        if( $this->x < 1 && $this->x > 0 ) $this->x *= $aImg->width;
     235        if( $this->y < 1 && $this->y > 0 ) $this->y *= $aImg->height;
     236
     237        $aImg->PushColor($this->color);
     238        $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
     239        $aImg->SetTextAlign($this->halign,$this->valign);
     240        if( $this->boxed ) {
     241            if( $this->fcolor=="nofill" )
     242                $this->fcolor=false;           
     243            $aImg->SetLineWeight(1);
     244            $bbox = $aImg->StrokeBoxedText($this->x,$this->y,$this->t,
     245                                   $this->dir,$this->fcolor,$this->bcolor,$this->shadow,
     246                                   $this->paragraph_align,5,5,$this->icornerradius,
     247                                   $this->ishadowwidth);
     248        }
     249        else {
     250            $bbox = $aImg->StrokeText($this->x,$this->y,$this->t,$this->dir,$this->paragraph_align);
     251        }
     252
     253        // Create CSIM targets
     254        $coords = $bbox[0].','.$bbox[1].','.$bbox[2].','.$bbox[3].','.$bbox[4].','.$bbox[5].','.$bbox[6].','.$bbox[7];
     255        $this->iCSIMarea = "<area shape=\"poly\" coords=\"$coords\" href=\"".htmlentities($this->iCSIMtarget)."\" ";
     256        if( trim($this->iCSIMalt) != '' ) {
     257            $this->iCSIMarea .= " alt=\"".$this->iCSIMalt."\" ";
     258            $this->iCSIMarea .= " title=\"".$this->iCSIMalt."\" ";
     259        }
     260        if( trim($this->iCSIMWinTarget) != '' ) {
     261            $this->iCSIMarea .= " target=\"".$this->iCSIMWinTarget."\" ";
     262        }
     263        $this->iCSIMarea .= " />\n";
     264
     265        $aImg->PopColor($this->color); 
     266
    323267    }
    324268} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_ttf.inc.php

    r265 r267  
    11<?php
    22//=======================================================================
    3 // File:        jpgraph_ttf.inc.php
    4 // Description: Handling of TTF fonts
    5 // Created:     2006-11-19
    6 // Ver:         $Id: jpgraph_ttf.inc.php 1858 2009-09-28 14:39:51Z ljp $
     3// File:        jpgraph_ttf.inc.php
     4// Description: Handling of TTF fonts
     5// Created:     2006-11-19
     6// Ver:         $Id: jpgraph_ttf.inc.php 1091 2009-01-18 22:57:40Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010
     
    2727define("FF_SIMSUN",30);
    2828define("FF_CHINESE",31);
    29 define("FF_BIG5",32);
     29define("FF_BIG5",31);
    3030
    3131// Japanese font
     
    4848
    4949// Extra fonts
    50 // Download fonts from
     50// Download fonts from 
    5151// http://www.webfontlist.com
    5252// http://www.webpagepublicity.com/free-fonts.html
    53 // http://www.fontonic.com/fonts.asp?width=d&offset=120
    54 // http://www.fontspace.com/category/famous
    55 
    56 // define("FF_SPEEDO",71);  // This font is also known as Bauer (Used for development gauge fascia)
    57 define("FF_DIGITAL",72); // Digital readout font
    58 define("FF_COMPUTER",73); // The classic computer font
    59 define("FF_CALCULATOR",74); // Triad font
     53
     54define("FF_SPEEDO",71);         // This font is also known as Bauer (Used for gauge fascia)
     55define("FF_DIGITAL",72);        // Digital readout font
     56define("FF_COMPUTER",73);       // The classic computer font
     57define("FF_CALCULATOR",74);     // Triad font
    6058
    6159define("FF_USERFONT",90);
     
    8078define("FF_FONT2",4);
    8179
    82 //------------------------------------------------------------------------
    83 // Defines for font setup
    84 //------------------------------------------------------------------------
    85 
    86 // Actual name of the TTF file used together with FF_CHINESE aka FF_BIG5
    87 // This is the TTF file being used when the font family is specified as
    88 // either FF_CHINESE or FF_BIG5
    89 define('CHINESE_TTF_FONT','bkai00mp.ttf');
    90 
    91 // Special unicode greek language support
    92 define("LANGUAGE_GREEK",false);
    93 
    94 // If you are setting this config to true the conversion of greek characters
    95 // will assume that the input text is windows 1251
    96 define("GREEK_FROM_WINDOWS",false);
    97 
    98 // Special unicode cyrillic language support
    99 define("LANGUAGE_CYRILLIC",false);
    100 
    101 // If you are setting this config to true the conversion
    102 // will assume that the input text is windows 1251, if
    103 // false it will assume koi8-r
    104 define("CYRILLIC_FROM_WINDOWS",false);
    105 
    106 // The following constant is used to auto-detect
    107 // whether cyrillic conversion is really necessary
    108 // if enabled. Just replace 'windows-1251' with a variable
    109 // containing the input character encoding string
    110 // of your application calling jpgraph.
    111 // A typical such string would be 'UTF-8' or 'utf-8'.
    112 // The comparison is case-insensitive.
    113 // If this charset is not a 'koi8-r' or 'windows-1251'
    114 // derivate then no conversion is done.
    115 //
    116 // This constant can be very important in multi-user
    117 // multi-language environments where a cyrillic conversion
    118 // could be needed for some cyrillic people
    119 // and resulting in just erraneous conversions
    120 // for not-cyrillic language based people.
    121 //
    122 // Example: In the free project management
    123 // software dotproject.net $locale_char_set is dynamically
    124 // set by the language environment the user has chosen.
    125 //
    126 // Usage: define('LANGUAGE_CHARSET', $locale_char_set);
    127 //
    128 // where $locale_char_set is a GLOBAL (string) variable
    129 // from the application including JpGraph.
    130 //
    131 define('LANGUAGE_CHARSET', null);
    132 
    133 // Japanese TrueType font used with FF_MINCHO, FF_PMINCHO, FF_GOTHIC, FF_PGOTHIC
    134 // Standard fonts from Infomation-technology Promotion Agency (IPA)
    135 // See http://mix-mplus-ipa.sourceforge.jp/
    136 define('MINCHO_TTF_FONT','ipam.ttf');
    137 define('PMINCHO_TTF_FONT','ipamp.ttf');
    138 define('GOTHIC_TTF_FONT','ipag.ttf');
    139 define('PGOTHIC_TTF_FONT','ipagp.ttf');
    140 
    141 // Assume that Japanese text have been entered in EUC-JP encoding.
    142 // If this define is true then conversion from EUC-JP to UTF8 is done
    143 // automatically in the library using the mbstring module in PHP.
    144 define('ASSUME_EUCJP_ENCODING',false);
    145 
    146 
    147 // Default font family
    148 define('FF_DEFAULT', FF_DV_SANSSERIF);
    149 
    150 
    151 
    15280//=================================================================
    15381// CLASS LanguageConv
    154 // Description:
     82// Description: 
    15583// Converts various character encoding into proper
    15684// UTF-8 depending on how the library have been configured and
     
    16189
    16290    function Convert($aTxt,$aFF) {
    163         if( LANGUAGE_GREEK ) {
    164             if( GREEK_FROM_WINDOWS ) {
    165                 $unistring = LanguageConv::gr_win2uni($aTxt);
    166             } else  {
    167                 $unistring = LanguageConv::gr_iso2uni($aTxt);
    168             }
    169             return $unistring;
    170         } elseif( LANGUAGE_CYRILLIC ) {
    171             if( CYRILLIC_FROM_WINDOWS && (!defined('LANGUAGE_CHARSET') || stristr(LANGUAGE_CHARSET, 'windows-1251')) ) {
    172                 $aTxt = convert_cyr_string($aTxt, "w", "k");
    173             }
    174             if( !defined('LANGUAGE_CHARSET') || stristr(LANGUAGE_CHARSET, 'koi8-r') || stristr(LANGUAGE_CHARSET, 'windows-1251')) {
    175                 $isostring = convert_cyr_string($aTxt, "k", "i");
    176                 $unistring = LanguageConv::iso2uni($isostring);
    177             }
    178             else {
    179                 $unistring = $aTxt;
    180             }
    181             return $unistring;
    182         }
    183         elseif( $aFF === FF_SIMSUN ) {
    184             // Do Chinese conversion
    185             if( $this->g2312 == null ) {
    186                 include_once 'jpgraph_gb2312.php' ;
    187                 $this->g2312 = new GB2312toUTF8();
    188             }
    189             return $this->g2312->gb2utf8($aTxt);
    190         }
    191         elseif( $aFF === FF_BIG5 ) {
    192             if( !function_exists('iconv') ) {
    193                 JpGraphError::RaiseL(25006);
    194                 //('Usage of FF_CHINESE (FF_BIG5) font family requires that your PHP setup has the iconv() function. By default this is not compiled into PHP (needs the "--width-iconv" when configured).');
    195             }
    196             return iconv('BIG5','UTF-8',$aTxt);
    197         }
    198         elseif( ASSUME_EUCJP_ENCODING &&
    199         ($aFF == FF_MINCHO || $aFF == FF_GOTHIC || $aFF == FF_PMINCHO || $aFF == FF_PGOTHIC) ) {
    200             if( !function_exists('mb_convert_encoding') ) {
    201                 JpGraphError::RaiseL(25127);
    202             }
    203             return mb_convert_encoding($aTxt, 'UTF-8','EUC-JP');
    204         }
    205         elseif( $aFF == FF_DAVID || $aFF == FF_MIRIAM || $aFF == FF_AHRON ) {
    206             return LanguageConv::heb_iso2uni($aTxt);
    207         }
    208         else
    209         return $aTxt;
     91        if( LANGUAGE_GREEK ) {
     92            if( GREEK_FROM_WINDOWS ) {
     93                $unistring = LanguageConv::gr_win2uni($aTxt);
     94            } else  {
     95                $unistring = LanguageConv::gr_iso2uni($aTxt);
     96            }
     97            return $unistring;
     98        } elseif( LANGUAGE_CYRILLIC ) {
     99            if( CYRILLIC_FROM_WINDOWS && (!defined('LANGUAGE_CHARSET') || stristr(LANGUAGE_CHARSET, 'windows-1251')) ) {
     100                $aTxt = convert_cyr_string($aTxt, "w", "k");
     101            }
     102            if( !defined('LANGUAGE_CHARSET') || stristr(LANGUAGE_CHARSET, 'koi8-r') || stristr(LANGUAGE_CHARSET, 'windows-1251')) {
     103                $isostring = convert_cyr_string($aTxt, "k", "i");
     104                $unistring = LanguageConv::iso2uni($isostring);
     105            }
     106            else {
     107                $unistring = $aTxt;
     108            }
     109            return $unistring;
     110        }
     111        elseif( $aFF === FF_SIMSUN ) {
     112            // Do Chinese conversion
     113            if( $this->g2312 == null ) {
     114                include_once 'jpgraph_gb2312.php' ;
     115                $this->g2312 = new GB2312toUTF8();
     116            }
     117            return $this->g2312->gb2utf8($aTxt);
     118        }
     119        elseif( $aFF === FF_CHINESE ) {
     120            if( !function_exists('iconv') ) {
     121                JpGraphError::RaiseL(25006);
     122//('Usage of FF_CHINESE (FF_BIG5) font family requires that your PHP setup has the iconv() function. By default this is not compiled into PHP (needs the "--width-iconv" when configured).');
     123            }
     124            return iconv('BIG5','UTF-8',$aTxt);
     125        }
     126        elseif( ASSUME_EUCJP_ENCODING &&
     127                ($aFF == FF_MINCHO || $aFF == FF_GOTHIC || $aFF == FF_PMINCHO || $aFF == FF_PGOTHIC) ) {
     128            if( !function_exists('mb_convert_encoding') ) {
     129                JpGraphError::RaiseL(25127);
     130            }
     131            return mb_convert_encoding($aTxt, 'UTF-8','EUC-JP');
     132        }
     133        elseif( $aFF == FF_DAVID || $aFF == FF_MIRIAM || $aFF == FF_AHRON ) {
     134            return LanguageConv::heb_iso2uni($aTxt);
     135        }
     136        else
     137            return $aTxt;
    210138    }
    211139
    212140    // Translate iso encoding to unicode
    213141    public static function iso2uni ($isoline){
    214         $uniline='';
    215         for ($i=0; $i < strlen($isoline); $i++){
    216             $thischar=substr($isoline,$i,1);
    217             $charcode=ord($thischar);
    218             $uniline.=($charcode>175) ? "&#" . (1040+($charcode-176)). ";" : $thischar;
    219         }
    220         return $uniline;
     142        $uniline='';
     143        for ($i=0; $i < strlen($isoline); $i++){
     144            $thischar=substr($isoline,$i,1);
     145            $charcode=ord($thischar);
     146            $uniline.=($charcode>175) ? "&#" . (1040+($charcode-176)). ";" : $thischar;
     147        }
     148        return $uniline;
    221149    }
    222150
    223151    // Translate greek iso encoding to unicode
    224152    public static function gr_iso2uni ($isoline) {
    225         $uniline='';
    226         for ($i=0; $i < strlen($isoline); $i++) {
    227             $thischar=substr($isoline,$i,1);
    228             $charcode=ord($thischar);
    229             $uniline.=($charcode>179 && $charcode!=183 && $charcode!=187 && $charcode!=189) ? "&#" . (900+($charcode-180)). ";" : $thischar;
    230         }
    231         return $uniline;
     153        $uniline='';
     154        for ($i=0; $i < strlen($isoline); $i++) {
     155            $thischar=substr($isoline,$i,1);
     156            $charcode=ord($thischar);
     157            $uniline.=($charcode>179 && $charcode!=183 && $charcode!=187 && $charcode!=189) ? "&#" . (900+($charcode-180)). ";" : $thischar;
     158        }
     159        return $uniline;
    232160    }
    233161
    234162    // Translate greek win encoding to unicode
    235163    public static function gr_win2uni ($winline) {
    236         $uniline='';
    237         for ($i=0; $i < strlen($winline); $i++) {
    238             $thischar=substr($winline,$i,1);
    239             $charcode=ord($thischar);
    240             if ($charcode==161 || $charcode==162) {
    241                 $uniline.="&#" . (740+$charcode). ";";
    242             }
    243             else {
    244                 $uniline.=(($charcode>183 && $charcode!=187 && $charcode!=189) || $charcode==180) ? "&#" . (900+($charcode-180)). ";" : $thischar;
    245             }
    246         }
    247         return $uniline;
     164        $uniline='';
     165        for ($i=0; $i < strlen($winline); $i++) {
     166            $thischar=substr($winline,$i,1);
     167            $charcode=ord($thischar);
     168            if ($charcode==161 || $charcode==162) {
     169                $uniline.="&#" . (740+$charcode). ";";
     170            }
     171            else {
     172                $uniline.=(($charcode>183 && $charcode!=187 && $charcode!=189) || $charcode==180) ? "&#" . (900+($charcode-180)). ";" : $thischar;
     173            }
     174        }
     175        return $uniline;
    248176    }
    249177
    250178    public static function heb_iso2uni($isoline) {
    251         $isoline = hebrev($isoline);
    252         $o = '';
    253 
    254         $n = strlen($isoline);
    255         for($i=0; $i < $n; $i++) {
    256             $c=ord( substr($isoline,$i,1) );
    257             $o .= ($c > 223) && ($c < 251) ? '&#'.(1264+$c).';' : chr($c);
    258         }
    259         return utf8_encode($o);
     179        $isoline = hebrev($isoline);
     180        $o = '';
     181
     182        $n = strlen($isoline);
     183        for($i=0; $i < $n; $i++) {
     184            $c=ord( substr($isoline,$i,1) );
     185            $o .= ($c > 223) && ($c < 251) ? '&#'.(1264+$c).';' : chr($c);
     186        }
     187        return utf8_encode($o);
    260188    }
    261189}
     
    263191//=============================================================
    264192// CLASS TTF
    265 // Description: Handle TTF font names and mapping and loading of
     193// Description: Handle TTF font names and mapping and loading of 
    266194//              font files
    267195//=============================================================
     
    269197    private $font_files,$style_names;
    270198
    271     function __construct() {
    272 
    273                 // String names for font styles to be used in error messages
    274             $this->style_names=array(
    275                 FS_NORMAL =>'normal',
    276                 FS_BOLD =>'bold',
    277                 FS_ITALIC =>'italic',
    278                 FS_BOLDITALIC =>'bolditalic');
    279 
    280             // File names for available fonts
    281             $this->font_files=array(
    282             FF_COURIER => array(FS_NORMAL =>'cour.ttf',
    283                 FS_BOLD  =>'courbd.ttf',
    284                 FS_ITALIC =>'couri.ttf',
    285                 FS_BOLDITALIC =>'courbi.ttf' ),
    286             FF_GEORGIA => array(FS_NORMAL =>'georgia.ttf',
    287                 FS_BOLD  =>'georgiab.ttf',
    288                 FS_ITALIC =>'georgiai.ttf',
    289                 FS_BOLDITALIC =>'' ),
    290             FF_TREBUCHE =>array(FS_NORMAL =>'trebuc.ttf',
    291                 FS_BOLD  =>'trebucbd.ttf',
    292                 FS_ITALIC =>'trebucit.ttf',
    293                 FS_BOLDITALIC =>'trebucbi.ttf' ),
    294             FF_VERDANA  => array(FS_NORMAL =>'verdana.ttf',
    295                 FS_BOLD  =>'verdanab.ttf',
    296                 FS_ITALIC =>'verdanai.ttf',
    297                 FS_BOLDITALIC =>'' ),
    298             FF_TIMES =>   array(FS_NORMAL =>'times.ttf',
    299                 FS_BOLD  =>'timesbd.ttf',
    300                 FS_ITALIC =>'timesi.ttf',
    301                 FS_BOLDITALIC =>'timesbi.ttf' ),
    302             FF_COMIC =>   array(FS_NORMAL =>'comic.ttf',
    303                 FS_BOLD  =>'comicbd.ttf',
    304                 FS_ITALIC =>'',
    305                 FS_BOLDITALIC =>'' ),
    306             FF_ARIAL =>   array(FS_NORMAL =>'arial.ttf',
    307                 FS_BOLD  =>'arialbd.ttf',
    308                 FS_ITALIC =>'ariali.ttf',
    309                 FS_BOLDITALIC =>'arialbi.ttf' ) ,
    310             FF_VERA =>    array(FS_NORMAL =>'Vera.ttf',
    311                 FS_BOLD  =>'VeraBd.ttf',
    312                 FS_ITALIC =>'VeraIt.ttf',
    313                 FS_BOLDITALIC =>'VeraBI.ttf' ),
    314             FF_VERAMONO => array(FS_NORMAL =>'VeraMono.ttf',
    315                 FS_BOLD =>'VeraMoBd.ttf',
    316                 FS_ITALIC =>'VeraMoIt.ttf',
    317                 FS_BOLDITALIC =>'VeraMoBI.ttf' ),
    318             FF_VERASERIF=> array(FS_NORMAL =>'VeraSe.ttf',
    319                 FS_BOLD =>'VeraSeBd.ttf',
    320                 FS_ITALIC =>'',
    321                 FS_BOLDITALIC =>'' ) ,
     199//---------------
     200// CONSTRUCTOR
     201    function TTF() {
     202
     203        // String names for font styles to be used in error messages
     204        $this->style_names=array(FS_NORMAL      =>'normal',
     205                                 FS_BOLD        =>'bold',
     206                                 FS_ITALIC      =>'italic',
     207                                 FS_BOLDITALIC  =>'bolditalic');
     208
     209        // File names for available fonts
     210        $this->font_files=array(
     211            FF_COURIER => array(FS_NORMAL       =>'cour.ttf',
     212                                FS_BOLD         =>'courbd.ttf',
     213                                FS_ITALIC       =>'couri.ttf',
     214                                FS_BOLDITALIC   =>'courbi.ttf' ),
     215            FF_GEORGIA => array(FS_NORMAL       =>'georgia.ttf',
     216                                FS_BOLD         =>'georgiab.ttf',
     217                                FS_ITALIC       =>'georgiai.ttf',
     218                                FS_BOLDITALIC   =>'' ),
     219            FF_TREBUCHE =>array(FS_NORMAL       =>'trebuc.ttf',
     220                                FS_BOLD         =>'trebucbd.ttf',   
     221                                FS_ITALIC       =>'trebucit.ttf',
     222                                FS_BOLDITALIC   =>'trebucbi.ttf' ),
     223            FF_VERDANA  => array(FS_NORMAL      =>'verdana.ttf',
     224                                FS_BOLD         =>'verdanab.ttf', 
     225                                FS_ITALIC       =>'verdanai.ttf',
     226                                FS_BOLDITALIC   =>'' ),
     227            FF_TIMES =>   array(FS_NORMAL       =>'times.ttf',   
     228                                FS_BOLD         =>'timesbd.ttf',   
     229                                FS_ITALIC       =>'timesi.ttf',   
     230                                FS_BOLDITALIC   =>'timesbi.ttf' ),
     231            FF_COMIC =>   array(FS_NORMAL       =>'comic.ttf',   
     232                                FS_BOLD         =>'comicbd.ttf',   
     233                                FS_ITALIC       =>'',         
     234                                FS_BOLDITALIC   =>'' ),
     235            FF_ARIAL =>   array(FS_NORMAL       =>'arial.ttf',   
     236                                FS_BOLD         =>'arialbd.ttf',   
     237                                FS_ITALIC       =>'ariali.ttf',   
     238                                FS_BOLDITALIC   =>'arialbi.ttf' ) ,
     239            FF_VERA =>    array(FS_NORMAL       =>'Vera.ttf',   
     240                                FS_BOLD         =>'VeraBd.ttf',   
     241                                FS_ITALIC       =>'VeraIt.ttf',   
     242                                FS_BOLDITALIC   =>'VeraBI.ttf' ),
     243            FF_VERAMONO => array(FS_NORMAL      =>'VeraMono.ttf',
     244                                 FS_BOLD        =>'VeraMoBd.ttf',
     245                                 FS_ITALIC      =>'VeraMoIt.ttf',
     246                                 FS_BOLDITALIC  =>'VeraMoBI.ttf' ),
     247            FF_VERASERIF=> array(FS_NORMAL      =>'VeraSe.ttf',
     248                                  FS_BOLD       =>'VeraSeBd.ttf',
     249                                  FS_ITALIC     =>'',
     250                                  FS_BOLDITALIC =>'' ) ,
    322251
    323252            /* Chinese fonts */
    324             FF_SIMSUN  =>  array(
    325                 FS_NORMAL =>'simsun.ttc',
    326                 FS_BOLD =>'simhei.ttf',
    327                 FS_ITALIC =>'',
    328                 FS_BOLDITALIC =>'' ),
    329             FF_CHINESE  =>   array(
    330                 FS_NORMAL =>CHINESE_TTF_FONT,
    331                 FS_BOLD =>'',
    332                 FS_ITALIC =>'',
    333                 FS_BOLDITALIC =>'' ),
    334             FF_BIG5  =>   array(
    335                 FS_NORMAL =>CHINESE_TTF_FONT,
    336                 FS_BOLD =>'',
    337                 FS_ITALIC =>'',
    338                 FS_BOLDITALIC =>'' ),
     253            FF_SIMSUN   =>  array(FS_NORMAL     =>'simsun.ttc', 
     254                                  FS_BOLD       =>'simhei.ttf',   
     255                                  FS_ITALIC     =>'',   
     256                                  FS_BOLDITALIC =>'' ),
     257            FF_CHINESE  =>   array(FS_NORMAL    =>CHINESE_TTF_FONT,
     258                                  FS_BOLD       =>'',
     259                                  FS_ITALIC     =>'',
     260                                  FS_BOLDITALIC =>'' ),
    339261
    340262            /* Japanese fonts */
    341             FF_MINCHO  =>  array(
    342                 FS_NORMAL =>MINCHO_TTF_FONT,
    343                 FS_BOLD =>'',
    344                 FS_ITALIC =>'',
    345                 FS_BOLDITALIC =>'' ),
    346 
    347             FF_PMINCHO  =>  array(
    348                 FS_NORMAL =>PMINCHO_TTF_FONT,
    349                 FS_BOLD =>'',
    350                 FS_ITALIC =>'',
    351                 FS_BOLDITALIC =>'' ),
    352 
    353             FF_GOTHIC   =>  array(
    354                 FS_NORMAL =>GOTHIC_TTF_FONT,
    355                 FS_BOLD =>'',
    356                 FS_ITALIC =>'',
    357                 FS_BOLDITALIC =>'' ),
    358 
    359             FF_PGOTHIC  =>  array(
    360                 FS_NORMAL =>PGOTHIC_TTF_FONT,
    361                 FS_BOLD =>'',
    362                 FS_ITALIC =>'',
    363                 FS_BOLDITALIC =>'' ),
     263            FF_MINCHO   =>  array(FS_NORMAL     =>MINCHO_TTF_FONT, 
     264                                  FS_BOLD       =>'',   
     265                                  FS_ITALIC     =>'',   
     266                                  FS_BOLDITALIC =>'' ),
     267            FF_PMINCHO  =>  array(FS_NORMAL     =>PMINCHO_TTF_FONT, 
     268                                  FS_BOLD       =>'',   
     269                                  FS_ITALIC     =>'', 
     270                                  FS_BOLDITALIC =>'' ),   
     271            FF_GOTHIC   =>  array(FS_NORMAL     =>GOTHIC_TTF_FONT, 
     272                                  FS_BOLD       =>'',   
     273                                  FS_ITALIC     =>'',   
     274                                  FS_BOLDITALIC =>'' ),   
     275            FF_PGOTHIC  =>  array(FS_NORMAL     =>PGOTHIC_TTF_FONT, 
     276                                  FS_BOLD       =>'',   
     277                                  FS_ITALIC     =>'', 
     278                                  FS_BOLDITALIC =>'' ),   
     279            FF_MINCHO   =>  array(FS_NORMAL     =>PMINCHO_TTF_FONT, 
     280                                  FS_BOLD       =>'',   
     281                                  FS_ITALIC     =>'', 
     282                                  FS_BOLDITALIC =>'' ),   
    364283
    365284            /* Hebrew fonts */
    366             FF_DAVID  =>  array(
    367                 FS_NORMAL =>'DAVIDNEW.TTF',
    368                 FS_BOLD =>'',
    369                 FS_ITALIC =>'',
    370                 FS_BOLDITALIC =>'' ),
    371 
    372             FF_MIRIAM  =>  array(
    373                 FS_NORMAL =>'MRIAMY.TTF',
    374                 FS_BOLD =>'',
    375                 FS_ITALIC =>'',
    376                 FS_BOLDITALIC =>'' ),
    377 
    378             FF_AHRON  =>  array(
    379                 FS_NORMAL =>'ahronbd.ttf',
    380                 FS_BOLD =>'',
    381                 FS_ITALIC =>'',
    382                 FS_BOLDITALIC =>'' ),
     285            FF_DAVID    =>  array(FS_NORMAL     =>'DAVIDNEW.TTF', 
     286                                  FS_BOLD       =>'',   
     287                                  FS_ITALIC     =>'', 
     288                                  FS_BOLDITALIC =>'' ),   
     289
     290            FF_MIRIAM   =>  array(FS_NORMAL     =>'MRIAMY.TTF', 
     291                                  FS_BOLD       =>'',   
     292                                  FS_ITALIC     =>'', 
     293                                  FS_BOLDITALIC =>'' ),   
     294
     295            FF_AHRON    =>  array(FS_NORMAL     =>'ahronbd.ttf', 
     296                                  FS_BOLD       =>'',   
     297                                  FS_ITALIC     =>'', 
     298                                  FS_BOLDITALIC =>'' ),   
    383299
    384300            /* Misc fonts */
    385             FF_DIGITAL =>   array(
    386                 FS_NORMAL =>'DIGIRU__.TTF',
    387                 FS_BOLD =>'Digirtu_.ttf',
    388                 FS_ITALIC =>'Digir___.ttf',
    389                 FS_BOLDITALIC =>'DIGIRT__.TTF' ),
    390 
    391             /* This is an experimental font for the speedometer development
    392             FF_SPEEDO =>    array(
    393             FS_NORMAL =>'Speedo.ttf',
    394             FS_BOLD =>'',
    395             FS_ITALIC =>'',
    396             FS_BOLDITALIC =>'' ),
    397             */
    398 
    399             FF_COMPUTER  =>  array(
    400                 FS_NORMAL =>'COMPUTER.TTF',
    401                 FS_BOLD =>'',
    402                 FS_ITALIC =>'',
    403                 FS_BOLDITALIC =>'' ),
    404 
    405             FF_CALCULATOR => array(
    406                 FS_NORMAL =>'Triad_xs.ttf',
    407                 FS_BOLD =>'',
    408                 FS_ITALIC =>'',
    409                 FS_BOLDITALIC =>'' ),
     301            FF_DIGITAL =>   array(FS_NORMAL     =>'DIGIRU__.TTF', 
     302                                  FS_BOLD       =>'Digirtu_.ttf',
     303                                  FS_ITALIC     =>'Digir___.ttf',
     304                                  FS_BOLDITALIC =>'DIGIRT__.TTF' ),   
     305            FF_SPEEDO =>    array(FS_NORMAL     =>'Speedo.ttf', 
     306                                  FS_BOLD       =>'',   
     307                                  FS_ITALIC     =>'',   
     308                                  FS_BOLDITALIC =>'' ),   
     309            FF_COMPUTER  =>  array(FS_NORMAL    =>'COMPUTER.TTF', 
     310                                  FS_BOLD       =>'',   
     311                                  FS_ITALIC     =>'',   
     312                                  FS_BOLDITALIC =>'' ),   
     313            FF_CALCULATOR => array(FS_NORMAL    =>'Triad_xs.ttf', 
     314                                  FS_BOLD       =>'',   
     315                                  FS_ITALIC     =>'',   
     316                                  FS_BOLDITALIC =>'' ), 
    410317
    411318            /* Dejavu fonts */
    412             FF_DV_SANSSERIF => array(
    413                 FS_NORMAL =>array('DejaVuSans.ttf'),
    414                 FS_BOLD =>array('DejaVuSans-Bold.ttf','DejaVuSansBold.ttf'),
    415                 FS_ITALIC =>array('DejaVuSans-Oblique.ttf','DejaVuSansOblique.ttf'),
    416                 FS_BOLDITALIC =>array('DejaVuSans-BoldOblique.ttf','DejaVuSansBoldOblique.ttf') ),
    417 
    418             FF_DV_SANSSERIFMONO => array(
    419                 FS_NORMAL =>array('DejaVuSansMono.ttf','DejaVuMonoSans.ttf'),
    420                 FS_BOLD =>array('DejaVuSansMono-Bold.ttf','DejaVuMonoSansBold.ttf'),
    421                 FS_ITALIC =>array('DejaVuSansMono-Oblique.ttf','DejaVuMonoSansOblique.ttf'),
    422                 FS_BOLDITALIC =>array('DejaVuSansMono-BoldOblique.ttf','DejaVuMonoSansBoldOblique.ttf') ),
    423 
    424             FF_DV_SANSSERIFCOND => array(
    425                 FS_NORMAL =>array('DejaVuSansCondensed.ttf','DejaVuCondensedSans.ttf'),
    426                 FS_BOLD =>array('DejaVuSansCondensed-Bold.ttf','DejaVuCondensedSansBold.ttf'),
    427                 FS_ITALIC =>array('DejaVuSansCondensed-Oblique.ttf','DejaVuCondensedSansOblique.ttf'),
    428                 FS_BOLDITALIC =>array('DejaVuSansCondensed-BoldOblique.ttf','DejaVuCondensedSansBoldOblique.ttf') ),
    429 
    430             FF_DV_SERIF => array(
    431                 FS_NORMAL =>array('DejaVuSerif.ttf'),
    432                 FS_BOLD =>array('DejaVuSerif-Bold.ttf','DejaVuSerifBold.ttf'),
    433                 FS_ITALIC =>array('DejaVuSerif-Italic.ttf','DejaVuSerifItalic.ttf'),
    434                 FS_BOLDITALIC =>array('DejaVuSerif-BoldItalic.ttf','DejaVuSerifBoldItalic.ttf') ),
    435 
    436             FF_DV_SERIFCOND => array(
    437                 FS_NORMAL =>array('DejaVuSerifCondensed.ttf','DejaVuCondensedSerif.ttf'),
    438                 FS_BOLD =>array('DejaVuSerifCondensed-Bold.ttf','DejaVuCondensedSerifBold.ttf'),
    439                 FS_ITALIC =>array('DejaVuSerifCondensed-Italic.ttf','DejaVuCondensedSerifItalic.ttf'),
    440                 FS_BOLDITALIC =>array('DejaVuSerifCondensed-BoldItalic.ttf','DejaVuCondensedSerifBoldItalic.ttf') ),
    441 
    442 
    443             /* Placeholders for defined fonts */
    444             FF_USERFONT1 => array(
    445                 FS_NORMAL =>'',
    446                 FS_BOLD =>'',
    447                 FS_ITALIC =>'',
    448                 FS_BOLDITALIC =>'' ),
    449 
    450             FF_USERFONT2 => array(
    451                 FS_NORMAL =>'',
    452                 FS_BOLD =>'',
    453                 FS_ITALIC =>'',
    454                 FS_BOLDITALIC =>'' ),
    455 
    456             FF_USERFONT3 => array(
    457                 FS_NORMAL =>'',
    458                 FS_BOLD =>'',
    459                 FS_ITALIC =>'',
    460                 FS_BOLDITALIC =>'' ),
    461 
    462             );
    463     }
    464 
    465     //---------------
    466     // PUBLIC METHODS
     319            FF_DV_SANSSERIF => array(FS_NORMAL  =>'DejaVuSans.ttf', 
     320                                  FS_BOLD       =>'DejaVuSans-Bold.ttf',   
     321                                  FS_ITALIC     =>'DejaVuSans-Oblique.ttf',   
     322                                  FS_BOLDITALIC =>'DejaVuSans-BoldOblique.ttf' ), 
     323
     324            FF_DV_SANSSERIFMONO => array(FS_NORMAL      =>'DejaVuSansMono.ttf', 
     325                                  FS_BOLD       =>'DejaVuSansMono-Bold.ttf',   
     326                                  FS_ITALIC     =>'DejaVuSansMono-Oblique.ttf',   
     327                                  FS_BOLDITALIC =>'DejaVuSansMono-BoldOblique.ttf' ), 
     328
     329            FF_DV_SANSSERIFCOND => array(FS_NORMAL      =>'DejaVuSansCondensed.ttf', 
     330                                  FS_BOLD       =>'DejaVuSansCondensed-Bold.ttf',   
     331                                  FS_ITALIC     =>'DejaVuSansCondensed-Oblique.ttf',   
     332                                  FS_BOLDITALIC =>'DejaVuSansCondensed-BoldOblique.ttf' ), 
     333
     334            FF_DV_SERIF => array(FS_NORMAL      =>'DejaVuSerif.ttf', 
     335                                  FS_BOLD       =>'DejaVuSerif-Bold.ttf',   
     336                                  FS_ITALIC     =>'DejaVuSerif-Italic.ttf',   
     337                                  FS_BOLDITALIC =>'DejaVuSerif-BoldItalic.ttf' ), 
     338
     339            FF_DV_SERIFCOND => array(FS_NORMAL  =>'DejaVuSerifCondensed.ttf', 
     340                                  FS_BOLD       =>'DejaVuSerifCondensed-Bold.ttf',   
     341                                  FS_ITALIC     =>'DejaVuSerifCondensed-Italic.ttf',   
     342                                  FS_BOLDITALIC =>'DejaVuSerifCondensed-BoldItalic.ttf' ), 
     343
     344
     345            /* User defined font */
     346            FF_USERFONT1 => array(FS_NORMAL     =>'', 
     347                                  FS_BOLD       =>'',   
     348                                  FS_ITALIC     =>'',   
     349                                  FS_BOLDITALIC =>'' ), 
     350
     351            FF_USERFONT2 => array(FS_NORMAL     =>'', 
     352                                  FS_BOLD       =>'',   
     353                                  FS_ITALIC     =>'',   
     354                                  FS_BOLDITALIC =>'' ), 
     355
     356            FF_USERFONT3 => array(FS_NORMAL     =>'', 
     357                                  FS_BOLD       =>'',   
     358                                  FS_ITALIC     =>'',   
     359                                  FS_BOLDITALIC =>'' ), 
     360
     361            );
     362    }
     363
     364//---------------
     365// PUBLIC METHODS       
    467366    // Create the TTF file from the font specification
    468367    function File($family,$style=FS_NORMAL) {
    469         $fam = @$this->font_files[$family];
    470         if( !$fam ) {
    471             JpGraphError::RaiseL(25046,$family);//("Specified TTF font family (id=$family) is unknown or does not exist. Please note that TTF fonts are not distributed with JpGraph for copyright reasons. You can find the MS TTF WEB-fonts (arial, courier etc) for download at http://corefonts.sourceforge.net/");
    472         }
    473         $ff = @$fam[$style];
    474 
    475         // There are several optional file names. They are tried in order
    476         // and the first one found is used
    477         if( !is_array($ff) ) {
    478             $ff = array($ff);
    479         }
    480 
    481         $jpgraph_font_dir = dirname(__FILE__).'/fonts/';
    482 
    483         foreach ($ff as $font_file) {
    484             // All font families are guaranteed to have the normal style
    485 
    486             if( $font_file==='' )
    487                     JpGraphError::RaiseL(25047,$this->style_names[$style],$this->font_files[$family][FS_NORMAL]);//('Style "'.$this->style_names[$style].'" is not available for font family '.$this->font_files[$family][FS_NORMAL].'.');
    488             if( !$font_file ) {
    489                 JpGraphError::RaiseL(25048,$fam);//("Unknown font style specification [$fam].");
    490             }
    491 
    492             // check jpgraph/src/fonts dir
    493             $jpgraph_font_file = $jpgraph_font_dir . $font_file;
    494             if (file_exists($jpgraph_font_file) === true && is_readable($jpgraph_font_file) === true) {
    495                 $font_file = $jpgraph_font_file;
    496                 break;
    497             }
    498 
    499             // check OS font dir
    500             if ($family >= FF_MINCHO && $family <= FF_PGOTHIC) {
    501                 $font_file = MBTTF_DIR.$font_file;
    502             } else {
    503                 $font_file = TTF_DIR.$font_file;
    504             }
    505             if (file_exists($font_file) === true && is_readable($font_file) === true) {
    506                 break;
    507             }
    508         }
    509 
    510         if( !file_exists($font_file) ) {
    511                 JpGraphError::RaiseL(25049,$font_file);//("Font file \"$font_file\" is not readable or does not exist.");
    512         }
    513 
    514         return $font_file;
     368        $fam = @$this->font_files[$family];
     369        if( !$fam ) {
     370            JpGraphError::RaiseL(25046,$family);//("Specified TTF font family (id=$family) is unknown or does not exist. Please note that TTF fonts are not distributed with JpGraph for copyright reasons. You can find the MS TTF WEB-fonts (arial, courier etc) for download at http://corefonts.sourceforge.net/");
     371        }
     372        $f = @$fam[$style];
     373
     374        if( $f==='' )
     375            JpGraphError::RaiseL(25047,$this->style_names[$style],$this->font_files[$family][FS_NORMAL]);//('Style "'.$this->style_names[$style].'" is not available for font family '.$this->font_files[$family][FS_NORMAL].'.');
     376        if( !$f ) {
     377            JpGraphError::RaiseL(25048,$fam);//("Unknown font style specification [$fam].");
     378        }
     379
     380        if ($family >= FF_MINCHO && $family <= FF_PGOTHIC) {
     381            $f = MBTTF_DIR.$f;
     382        } else {
     383            $f = TTF_DIR.$f;
     384        }
     385
     386        if( file_exists($f) === false || is_readable($f) === false ) {
     387            JpGraphError::RaiseL(25049,$f);//("Font file \"$f\" is not readable or does not exist.");
     388        }
     389        return $f;
    515390    }
    516391
    517392    function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    518         $this->font_files[FF_USERFONT] =
    519                 array(FS_NORMAL     => $aNormal,
    520                           FS_BOLD => $aBold,
    521                           FS_ITALIC => $aItalic,
    522                           FS_BOLDITALIC => $aBoldIt ) ;
     393        $this->font_files[FF_USERFONT] =
     394            array(FS_NORMAL     => $aNormal, 
     395                  FS_BOLD       => $aBold,   
     396                  FS_ITALIC     => $aItalic,   
     397                  FS_BOLDITALIC => $aBoldIt ) ;
    523398    }
    524399
    525400    function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    526         $this->font_files[FF_USERFONT1] =
    527                 array(FS_NORMAL     => $aNormal,
    528                           FS_BOLD => $aBold,
    529                           FS_ITALIC => $aItalic,
    530                           FS_BOLDITALIC => $aBoldIt ) ;
     401        $this->font_files[FF_USERFONT1] =
     402            array(FS_NORMAL     => $aNormal, 
     403                  FS_BOLD       => $aBold,   
     404                  FS_ITALIC     => $aItalic,   
     405                  FS_BOLDITALIC => $aBoldIt ) ;
    531406    }
    532407
    533408    function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    534         $this->font_files[FF_USERFONT2] =
    535                 array(FS_NORMAL     => $aNormal,
    536                           FS_BOLD => $aBold,
    537                           FS_ITALIC => $aItalic,
    538                           FS_BOLDITALIC => $aBoldIt ) ;
     409        $this->font_files[FF_USERFONT2] =
     410            array(FS_NORMAL     => $aNormal, 
     411                  FS_BOLD       => $aBold,   
     412                  FS_ITALIC     => $aItalic,   
     413                  FS_BOLDITALIC => $aBoldIt ) ;
    539414    }
    540415
    541416    function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    542         $this->font_files[FF_USERFONT3] =
    543                 array(FS_NORMAL     => $aNormal,
    544                           FS_BOLD => $aBold,
    545                           FS_ITALIC => $aItalic,
    546                           FS_BOLDITALIC => $aBoldIt ) ;
     417        $this->font_files[FF_USERFONT3] =
     418            array(FS_NORMAL     => $aNormal, 
     419                  FS_BOLD       => $aBold,   
     420                  FS_ITALIC     => $aItalic,   
     421                  FS_BOLDITALIC => $aBoldIt ) ;
    547422    }
    548423
     
    550425
    551426
    552 //=============================================================================
    553 // CLASS SymChar
    554 // Description: Code values for some commonly used characters that
    555 //              normally isn't available directly on the keyboard, for example
    556 //              mathematical and greek symbols.
    557 //=============================================================================
    558 class  SymChar {
    559     static function Get($aSymb,$aCapital=FALSE) {
    560         $iSymbols = array(
    561         /* Greek */
    562         array('alpha','03B1','0391'),
    563         array('beta','03B2','0392'),
    564         array('gamma','03B3','0393'),
    565         array('delta','03B4','0394'),
    566         array('epsilon','03B5','0395'),
    567         array('zeta','03B6','0396'),
    568         array('ny','03B7','0397'),
    569         array('eta','03B8','0398'),
    570         array('theta','03B8','0398'),
    571         array('iota','03B9','0399'),
    572         array('kappa','03BA','039A'),
    573         array('lambda','03BB','039B'),
    574         array('mu','03BC','039C'),
    575         array('nu','03BD','039D'),
    576         array('xi','03BE','039E'),
    577         array('omicron','03BF','039F'),
    578         array('pi','03C0','03A0'),
    579         array('rho','03C1','03A1'),
    580         array('sigma','03C3','03A3'),
    581         array('tau','03C4','03A4'),
    582         array('upsilon','03C5','03A5'),
    583         array('phi','03C6','03A6'),
    584         array('chi','03C7','03A7'),
    585         array('psi','03C8','03A8'),
    586         array('omega','03C9','03A9'),
    587         /* Money */
    588         array('euro','20AC'),
    589         array('yen','00A5'),
    590         array('pound','20A4'),
    591         /* Math */
    592         array('approx','2248'),
    593         array('neq','2260'),
    594         array('not','2310'),
    595         array('def','2261'),
    596         array('inf','221E'),
    597         array('sqrt','221A'),
    598         array('int','222B'),
    599         /* Misc */
    600         array('copy','00A9'),
    601         array('para','00A7'),
    602         array('tm','2122'),   /* Trademark symbol */
    603         array('rtm','00AE'),   /* Registered trademark */
    604         array('degree','00b0'),
    605         array('lte','2264'), /* Less than or equal */
    606         array('gte','2265'), /* Greater than or equal */
    607 
    608         );
    609 
    610         $n = count($iSymbols);
    611         $i=0;
    612         $found = false;
    613         $aSymb = strtolower($aSymb);
    614         while( $i < $n && !$found ) {
    615             $found = $aSymb === $iSymbols[$i++][0];
    616         }
    617         if( $found ) {
    618             $ca = $iSymbols[--$i];
    619             if( $aCapital && count($ca)==3 )
    620                 $s = $ca[2];
    621             else
    622                 $s = $ca[1];
    623             return sprintf('&#%04d;',hexdec($s));
    624         }
    625         else
    626             return '';
    627     }
    628 }
    629 
    630427
    631428?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_utils.inc.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3  // File:        JPGRAPH_UTILS.INC
    4  // Description: Collection of non-essential "nice to have" utilities
    5  // Created:     2005-11-20
    6  // Ver:         $Id: jpgraph_utils.inc.php 1777 2009-08-23 17:34:36Z ljp $
    7  //
    8  // Copyright (c) Asial Corporation. All rights reserved.
    9  //========================================================================
    10  */
     3// File:        JPGRAPH_UTILS.INC
     4// Description: Collection of non-essential "nice to have" utilities
     5// Created:     2005-11-20
     6// Ver:         $Id: jpgraph_utils.inc.php 1091 2009-01-18 22:57:40Z ljp $
     7//
     8// Copyright (c) Aditus Consulting. All rights reserved.
     9//========================================================================
     10*/
    1111
    1212//===================================================
    1313// CLASS FuncGenerator
    14 // Description: Utility class to help generate data for function plots.
     14// Description: Utility class to help generate data for function plots. 
    1515// The class supports both parametric and regular functions.
    1616//===================================================
    1717class FuncGenerator {
    1818    private $iFunc='',$iXFunc='',$iMin,$iMax,$iStepSize;
    19 
    20     function __construct($aFunc,$aXFunc='') {
    21         $this->iFunc = $aFunc;
    22         $this->iXFunc = $aXFunc;
    23     }
    24 
     19       
     20    function FuncGenerator($aFunc,$aXFunc='') {
     21        $this->iFunc = $aFunc;
     22        $this->iXFunc = $aXFunc;
     23    }
     24       
    2525    function E($aXMin,$aXMax,$aSteps=50) {
    26         $this->iMin = $aXMin;
    27         $this->iMax = $aXMax;
    28         $this->iStepSize = ($aXMax-$aXMin)/$aSteps;
    29 
    30         if( $this->iXFunc != '' )
    31         $t = 'for($i='.$aXMin.'; $i<='.$aXMax.'; $i += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]='.$this->iXFunc.';}';
    32         elseif( $this->iFunc != '' )
    33         $t = 'for($x='.$aXMin.'; $x<='.$aXMax.'; $x += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]=$x;} $x='.$aXMax.';$ya[]='.$this->iFunc.';$xa[]=$x;';
    34         else
    35         JpGraphError::RaiseL(24001);//('FuncGenerator : No function specified. ');
    36 
    37         @eval($t);
    38 
    39         // If there is an error in the function specifcation this is the only
    40         // way we can discover that.
    41         if( empty($xa) || empty($ya) )
    42         JpGraphError::RaiseL(24002);//('FuncGenerator : Syntax error in function specification ');
    43 
    44         return array($xa,$ya);
     26        $this->iMin = $aXMin;
     27        $this->iMax = $aXMax;
     28        $this->iStepSize = ($aXMax-$aXMin)/$aSteps;
     29
     30        if( $this->iXFunc != '' )
     31            $t = 'for($i='.$aXMin.'; $i<='.$aXMax.'; $i += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]='.$this->iXFunc.';}';
     32        elseif( $this->iFunc != '' )
     33            $t = 'for($x='.$aXMin.'; $x<='.$aXMax.'; $x += '.$this->iStepSize.') {$ya[]='.$this->iFunc.';$xa[]=$x;} $x='.$aXMax.';$ya[]='.$this->iFunc.';$xa[]=$x;';
     34        else
     35            JpGraphError::RaiseL(24001);//('FuncGenerator : No function specified. ');
     36                       
     37        @eval($t);
     38               
     39        // If there is an error in the function specifcation this is the only
     40        // way we can discover that.
     41        if( empty($xa) || empty($ya) )
     42            JpGraphError::RaiseL(24002);//('FuncGenerator : Syntax error in function specification ');
     43                               
     44        return array($xa,$ya);
     45    }
     46}
     47
     48//=============================================================================
     49// CLASS SymChar
     50// Description: Code values for some commonly used characters that
     51//              normally isn't available directly on the keyboard, for example
     52//              mathematical and greek symbols.
     53//=============================================================================
     54class  SymChar {
     55    static function Get($aSymb,$aCapital=FALSE) {
     56        $iSymbols = array(
     57    /* Greek */
     58        array('alpha','03B1','0391'),
     59        array('beta','03B2','0392'),
     60        array('gamma','03B3','0393'),
     61        array('delta','03B4','0394'),
     62        array('epsilon','03B5','0395'),
     63        array('zeta','03B6','0396'),
     64        array('ny','03B7','0397'),
     65        array('eta','03B8','0398'),
     66        array('theta','03B8','0398'),
     67        array('iota','03B9','0399'),
     68        array('kappa','03BA','039A'),
     69        array('lambda','03BB','039B'),
     70        array('mu','03BC','039C'),
     71        array('nu','03BD','039D'),
     72        array('xi','03BE','039E'),
     73        array('omicron','03BF','039F'),
     74        array('pi','03C0','03A0'),
     75        array('rho','03C1','03A1'),
     76        array('sigma','03C3','03A3'),
     77        array('tau','03C4','03A4'),
     78        array('upsilon','03C5','03A5'),
     79        array('phi','03C6','03A6'),
     80        array('chi','03C7','03A7'),
     81        array('psi','03C8','03A8'),
     82        array('omega','03C9','03A9'),
     83    /* Money */
     84        array('euro','20AC'),
     85        array('yen','00A5'),
     86        array('pound','20A4'),
     87    /* Math */
     88        array('approx','2248'),
     89        array('neq','2260'),
     90        array('not','2310'),
     91        array('def','2261'),
     92        array('inf','221E'),
     93        array('sqrt','221A'),
     94        array('int','222B'),
     95    /* Misc */
     96        array('copy','00A9'),
     97        array('para','00A7'),
     98        array('tm','2122'),   /* Trademark symbol */
     99        array('rtm','00AE')   /* Registered trademark */
     100
     101);
     102
     103        $n = count($iSymbols);
     104        $i=0;
     105        $found = false;
     106        $aSymb = strtolower($aSymb);
     107        while( $i < $n && !$found ) {
     108            $found = $aSymb === $iSymbols[$i++][0];
     109        }
     110        if( $found ) {
     111            $ca = $iSymbols[--$i];
     112            if( $aCapital && count($ca)==3 )
     113                $s = $ca[2];
     114            else
     115                $s = $ca[1];
     116            return sprintf('&#%04d;',hexdec($s));
     117        }
     118        else
     119            return '';
    45120    }
    46121}
     
    76151
    77152    static function UseWeekFormat($aFlg) {
    78         self::$iUseWeeks = $aFlg;
     153        self::$iUseWeeks = $aFlg;
    79154    }
    80155
    81156    static function doYearly($aType,$aMinor=false) {
    82         $i=0; $j=0;
    83         $m = self::$startmonth;
    84         $y = self::$startyear;
    85 
    86         if( self::$startday == 1 ) {
    87             self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
    88         }
    89         ++$m;
    90 
    91 
    92         switch( $aType ) {
    93             case DSUTILS_YEAR1:
    94                 for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
    95                     if( $aMinor ) {
    96                         while( $m <= 12 ) {
    97                             if( !($y == self::$endyear && $m > self::$endmonth) ) {
    98                                 self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
    99                             }
    100                             ++$m;
    101                         }
    102                         $m=1;
    103                     }
    104                     self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
    105                 }
    106                 break;
    107             case DSUTILS_YEAR2:
    108                 $y=self::$startyear;
    109                 while( $y <= self::$endyear ) {
    110                     self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
    111                     for($k=0; $k < 1; ++$k ) {
    112                         ++$y;
    113                         if( $aMinor ) {
    114                             self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
    115                         }
    116                     }
    117                     ++$y;
    118                 }
    119                 break;
    120             case DSUTILS_YEAR5:
    121                 $y=self::$startyear;
    122                 while( $y <= self::$endyear ) {
    123                     self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);
    124                     for($k=0; $k < 4; ++$k ) {
    125                         ++$y;
    126                         if( $aMinor ) {
    127                             self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
    128                         }
    129                     }
    130                     ++$y;
    131                 }
    132                 break;
    133         }
     157        $i=0; $j=0;
     158        $m = self::$startmonth;
     159        $y = self::$startyear;
     160
     161        if( self::$startday == 1 ) {
     162            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     163        }
     164        ++$m;
     165
     166
     167        switch( $aType ) {
     168            case DSUTILS_YEAR1:
     169                for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
     170                    if( $aMinor ) {
     171                        while( $m <= 12 ) {
     172                            if( !($y == self::$endyear && $m > self::$endmonth) ) {
     173                                self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
     174                            }
     175                            ++$m;
     176                        }
     177                        $m=1;
     178                    }
     179                    self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);   
     180                }
     181                break;
     182            case DSUTILS_YEAR2:
     183                $y=self::$startyear;
     184                while( $y <= self::$endyear ) {
     185                    self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);   
     186                    for($k=0; $k < 1; ++$k ) {
     187                        ++$y;
     188                        if( $aMinor ) {
     189                            self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
     190                        }
     191                    }
     192                    ++$y;
     193                }
     194                break;
     195            case DSUTILS_YEAR5:
     196                $y=self::$startyear;
     197                while( $y <= self::$endyear ) {
     198                    self::$tickPositions[$i++] = mktime(0,0,0,1,1,$y);   
     199                    for($k=0; $k < 4; ++$k ) {
     200                        ++$y;
     201                        if( $aMinor ) {
     202                            self::$minTickPositions[$j++] = mktime(0,0,0,1,1,$y);
     203                        }
     204                    }
     205                    ++$y;
     206                }
     207                break;
     208        }
    134209    }
    135210
    136211    static function doDaily($aType,$aMinor=false) {
    137         $m = self::$startmonth;
    138         $y = self::$startyear;
    139         $d = self::$startday;
    140         $h = self::$starthour;
    141         $i=0;$j=0;
    142 
    143         if( $h == 0 ) {
    144             self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
    145         }
    146         $t = mktime(0,0,0,$m,$d,$y);
    147 
    148         switch($aType) {
    149             case DSUTILS_DAY1:
    150                 while( $t <= self::$iMax ) {
    151                     $t = strtotime('+1 day',$t);
    152                     self::$tickPositions[$i++] = $t;
    153                     if( $aMinor ) {
    154                         self::$minTickPositions[$j++] = strtotime('+12 hours',$t);
    155                     }
    156                 }
    157                 break;
    158             case DSUTILS_DAY2:
    159                 while( $t <= self::$iMax ) {
    160                     $t = strtotime('+1 day',$t);
    161                     if( $aMinor ) {
    162                         self::$minTickPositions[$j++] = $t;
    163                     }
    164                     $t = strtotime('+1 day',$t);
    165                     self::$tickPositions[$i++] = $t;
    166                 }
    167                 break;
    168             case DSUTILS_DAY4:
    169                 while( $t <= self::$iMax ) {
    170                     for($k=0; $k < 3; ++$k ) {
    171                         $t = strtotime('+1 day',$t);
    172                         if( $aMinor ) {
    173                             self::$minTickPositions[$j++] = $t;
    174                         }
    175                     }
    176                     $t = strtotime('+1 day',$t);
    177                     self::$tickPositions[$i++] = $t;
    178                 }
    179                 break;
    180         }
     212        $m = self::$startmonth;
     213        $y = self::$startyear;
     214        $d = self::$startday;
     215        $h = self::$starthour;
     216        $i=0;$j=0;
     217
     218        if( $h == 0 ) {
     219            self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
     220        }
     221        $t = mktime(0,0,0,$m,$d,$y);       
     222
     223        switch($aType) {
     224            case DSUTILS_DAY1:
     225                while( $t <= self::$iMax ) {
     226                    $t = strtotime('+1 day',$t);
     227                    self::$tickPositions[$i++] = $t;
     228                    if( $aMinor ) {
     229                        self::$minTickPositions[$j++] = strtotime('+12 hours',$t);
     230                    }
     231                }
     232                break;
     233            case DSUTILS_DAY2:
     234                while( $t <= self::$iMax ) {
     235                    $t = strtotime('+1 day',$t);
     236                    if( $aMinor ) {
     237                        self::$minTickPositions[$j++] = $t;
     238                    }
     239                    $t = strtotime('+1 day',$t);
     240                    self::$tickPositions[$i++] = $t;
     241                }
     242                break;
     243            case DSUTILS_DAY4:
     244                while( $t <= self::$iMax ) {
     245                    for($k=0; $k < 3; ++$k ) {
     246                        $t = strtotime('+1 day',$t);
     247                        if( $aMinor ) {
     248                            self::$minTickPositions[$j++] = $t;
     249                        }
     250                    }
     251                    $t = strtotime('+1 day',$t);
     252                    self::$tickPositions[$i++] = $t;
     253                }
     254                break;
     255        }
    181256    }
    182257
    183258    static function doWeekly($aType,$aMinor=false) {
    184         $hpd = 3600*24;
    185         $hpw = 3600*24*7;
    186         // Find out week number of min date
    187         $thursday = self::$iMin + $hpd * (3 - (date('w', self::$iMin) + 6) % 7);
    188         $week = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7;
    189         $daynumber = date('w',self::$iMin);
    190         if( $daynumber == 0 ) $daynumber = 7;
    191         $m = self::$startmonth;
    192         $y = self::$startyear;
    193         $d = self::$startday;
    194         $i=0;$j=0;
    195         // The assumption is that the weeks start on Monday. If the first day
    196         // is later in the week then the first week tick has to be on the following
    197         // week.
    198         if( $daynumber == 1 ) {
    199             self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
    200             $t = mktime(0,0,0,$m,$d,$y) + $hpw;
    201         }
    202         else {
    203             $t = mktime(0,0,0,$m,$d,$y) + $hpd*(8-$daynumber);
    204         }
    205 
    206         switch($aType) {
    207             case DSUTILS_WEEK1:
    208                 $cnt=0;
    209                 break;
    210             case DSUTILS_WEEK2:
    211                 $cnt=1;
    212                 break;
    213             case DSUTILS_WEEK4:
    214                 $cnt=3;
    215                 break;
    216         }
    217         while( $t <= self::$iMax ) {
    218             self::$tickPositions[$i++] = $t;
    219             for($k=0; $k < $cnt; ++$k ) {
    220                 $t += $hpw;
    221                 if( $aMinor ) {
    222                     self::$minTickPositions[$j++] = $t;
    223                 }
    224             }
    225             $t += $hpw;
    226         }
     259        $hpd = 3600*24;
     260        $hpw = 3600*24*7;
     261        // Find out week number of min date
     262        $thursday = self::$iMin + $hpd * (3 - (date('w', self::$iMin) + 6) % 7);
     263        $week = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7;
     264        $daynumber = date('w',self::$iMin);
     265        if( $daynumber == 0 ) $daynumber = 7;
     266        $m = self::$startmonth;
     267        $y = self::$startyear;
     268        $d = self::$startday;
     269        $i=0;$j=0;
     270        // The assumption is that the weeks start on Monday. If the first day
     271        // is later in the week then the first week tick has to be on the following
     272        // week.
     273        if( $daynumber == 1 ) {
     274            self::$tickPositions[$i++] = mktime(0,0,0,$m,$d,$y);
     275            $t = mktime(0,0,0,$m,$d,$y) + $hpw;
     276        }
     277        else {
     278            $t = mktime(0,0,0,$m,$d,$y) + $hpd*(8-$daynumber);
     279        }
     280
     281        switch($aType) {
     282            case DSUTILS_WEEK1:
     283                $cnt=0;
     284                break;
     285            case DSUTILS_WEEK2:
     286                $cnt=1;
     287                break;
     288            case DSUTILS_WEEK4:
     289                $cnt=3;
     290                break;
     291        }
     292        while( $t <= self::$iMax ) {
     293            self::$tickPositions[$i++] = $t;
     294            for($k=0; $k < $cnt; ++$k ) {
     295                $t += $hpw;
     296                if( $aMinor ) {
     297                    self::$minTickPositions[$j++] = $t;
     298                }
     299            }
     300            $t += $hpw;
     301        }
    227302    }
    228303
    229304    static function doMonthly($aType,$aMinor=false) {
    230         $monthcount=0;
    231         $m = self::$startmonth;
    232         $y = self::$startyear;
    233         $i=0; $j=0;
    234 
    235         // Skip the first month label if it is before the startdate
    236         if( self::$startday == 1 ) {
    237             self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
    238             $monthcount=1;
    239         }
    240         if( $aType == 1 ) {
    241             if( self::$startday < 15 ) {
    242                 self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
    243             }
    244         }
    245         ++$m;
    246 
    247         // Loop through all the years included in the scale
    248         for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
    249             // Loop through all the months. There are three cases to consider:
    250             // 1. We are in the first year and must start with the startmonth
    251             // 2. We are in the end year and we must stop at last month of the scale
    252             // 3. A year in between where we run through all the 12 months
    253             $stopmonth = $y == self::$endyear ? self::$endmonth : 12;
    254             while( $m <= $stopmonth ) {
    255                 switch( $aType ) {
    256                     case DSUTILS_MONTH1:
    257                         // Set minor tick at the middle of the month
    258                         if( $aMinor ) {
    259                             if( $m <= $stopmonth ) {
    260                                 if( !($y==self::$endyear && $m==$stopmonth && self::$endday < 15) )
    261                                 self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
    262                             }
    263                         }
    264                         // Major at month
    265                         // Get timestamp of first hour of first day in each month
    266                         self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
    267 
    268                         break;
    269                     case DSUTILS_MONTH2:
    270                         if( $aMinor ) {
    271                             // Set minor tick at start of each month
    272                             self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
    273                         }
    274 
    275                         // Major at every second month
    276                         // Get timestamp of first hour of first day in each month
    277                         if( $monthcount % 2 == 0 ) {
    278                             self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
    279                         }
    280                         break;
    281                     case DSUTILS_MONTH3:
    282                         if( $aMinor ) {
    283                             // Set minor tick at start of each month
    284                             self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
    285                         }
    286                         // Major at every third month
    287                         // Get timestamp of first hour of first day in each month
    288                         if( $monthcount % 3 == 0 ) {
    289                             self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
    290                         }
    291                         break;
    292                     case DSUTILS_MONTH6:
    293                         if( $aMinor ) {
    294                             // Set minor tick at start of each month
    295                             self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
    296                         }
    297                         // Major at every third month
    298                         // Get timestamp of first hour of first day in each month
    299                         if( $monthcount % 6 == 0 ) {
    300                             self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
    301                         }
    302                         break;
    303                 }
    304                 ++$m;
    305                 ++$monthcount;
    306             }
    307             $m=1;
    308         }
    309 
    310         // For the case where all dates are within the same month
    311         // we want to make sure we have at least two ticks on the scale
    312         // since the scale want work properly otherwise
    313         if(self::$startmonth == self::$endmonth && self::$startyear == self::$endyear && $aType==1 ) {
    314             self::$tickPositions[$i++] = mktime(0 ,0 ,0, self::$startmonth + 1, 1, self::$startyear);
    315         }
    316 
    317         return array(self::$tickPositions,self::$minTickPositions);
     305        $monthcount=0;
     306        $m = self::$startmonth;
     307        $y = self::$startyear;
     308        $i=0; $j=0;
     309
     310        // Skip the first month label if it is before the startdate
     311        if( self::$startday == 1 ) {
     312            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     313            $monthcount=1;
     314        }
     315        if( $aType == 1 ) {
     316            if( self::$startday < 15 ) {
     317                self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
     318            }
     319        }
     320        ++$m;
     321
     322        // Loop through all the years included in the scale
     323        for($y=self::$startyear; $y <= self::$endyear; ++$y ) {
     324            // Loop through all the months. There are three cases to consider:
     325            // 1. We are in the first year and must start with the startmonth
     326            // 2. We are in the end year and we must stop at last month of the scale
     327            // 3. A year in between where we run through all the 12 months
     328            $stopmonth = $y == self::$endyear ? self::$endmonth : 12;
     329            while( $m <= $stopmonth ) {
     330                switch( $aType ) {
     331                    case DSUTILS_MONTH1:
     332                        // Set minor tick at the middle of the month
     333                        if( $aMinor ) {
     334                            if( $m <= $stopmonth ) {
     335                                if( !($y==self::$endyear && $m==$stopmonth && self::$endday < 15) )
     336                                self::$minTickPositions[$j++] = mktime(0,0,0,$m,15,$y);
     337                            }
     338                        }
     339                        // Major at month
     340                        // Get timestamp of first hour of first day in each month
     341                        self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     342
     343                        break;
     344                    case DSUTILS_MONTH2:
     345                        if( $aMinor ) {
     346                            // Set minor tick at start of each month
     347                            self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
     348                        }
     349
     350                        // Major at every second month
     351                        // Get timestamp of first hour of first day in each month
     352                        if( $monthcount % 2 == 0 ) {
     353                            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     354                        }
     355                        break;
     356                    case DSUTILS_MONTH3:
     357                        if( $aMinor ) {
     358                            // Set minor tick at start of each month
     359                            self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
     360                        }
     361                            // Major at every third month
     362                        // Get timestamp of first hour of first day in each month
     363                        if( $monthcount % 3 == 0 ) {
     364                            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     365                        }
     366                        break;
     367                    case DSUTILS_MONTH6:
     368                        if( $aMinor ) {
     369                            // Set minor tick at start of each month
     370                            self::$minTickPositions[$j++] = mktime(0,0,0,$m,1,$y);
     371                        }
     372                        // Major at every third month
     373                        // Get timestamp of first hour of first day in each month
     374                        if( $monthcount % 6 == 0 ) {
     375                            self::$tickPositions[$i++] = mktime(0,0,0,$m,1,$y);
     376                        }
     377                        break;
     378                }
     379                ++$m;
     380                ++$monthcount;
     381            }
     382            $m=1;
     383        }
     384
     385        // For the case where all dates are within the same month
     386        // we want to make sure we have at least two ticks on the scale
     387        // since the scale want work properly otherwise
     388        if(self::$startmonth == self::$endmonth && self::$startyear == self::$endyear && $aType==1 ) {
     389            self::$tickPositions[$i++] = mktime(0 ,0 ,0, self::$startmonth + 1, 1, self::$startyear);
     390        }
     391
     392        return array(self::$tickPositions,self::$minTickPositions);
    318393    }
    319394
    320395    static function GetTicks($aData,$aType=1,$aMinor=false,$aEndPoints=false) {
    321         $n = count($aData);
    322         return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints);
     396        $n = count($aData);
     397        return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints);
    323398    }
    324399
    325400    static function GetAutoTicks($aMin,$aMax,$aMaxTicks=10,$aMinor=false) {
    326         $diff = $aMax - $aMin;
    327         $spd = 3600*24;
    328         $spw = $spd*7;
    329         $spm = $spd*30;
    330         $spy = $spd*352;
    331 
    332         if( self::$iUseWeeks )
    333         $w = 'W';
    334         else
    335         $w = 'd M';
    336 
    337         // Decision table for suitable scales
    338         // First value: Main decision point
    339         // Second value: Array of formatting depending on divisor for wanted max number of ticks. <divisor><formatting><format-string>,..
    340         $tt = array(
    341             array($spw, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',-1,DSUTILS_DAY4,'d M')),
    342             array($spm, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M',7,DSUTILS_WEEK1,$w,-1,DSUTILS_WEEK2,$w)),
    343             array($spy, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M',7,DSUTILS_WEEK1,$w,14,DSUTILS_WEEK2,$w,30,DSUTILS_MONTH1,'M',60,DSUTILS_MONTH2,'M',-1,DSUTILS_MONTH3,'M')),
    344             array(-1, array(30,DSUTILS_MONTH1,'M-Y',60,DSUTILS_MONTH2,'M-Y',90,DSUTILS_MONTH3,'M-Y',180,DSUTILS_MONTH6,'M-Y',352,DSUTILS_YEAR1,'Y',704,DSUTILS_YEAR2,'Y',-1,DSUTILS_YEAR5,'Y')));
    345 
    346         $ntt = count($tt);
    347         $nd = floor($diff/$spd);
    348         for($i=0; $i < $ntt; ++$i ) {
    349             if( $diff <= $tt[$i][0] || $i==$ntt-1) {
    350                 $t = $tt[$i][1];
    351                 $n = count($t)/3;
    352                 for( $j=0; $j < $n; ++$j ) {
    353                     if( $nd/$t[3*$j] <= $aMaxTicks || $j==$n-1) {
    354                         $type = $t[3*$j+1];
    355                         $fs = $t[3*$j+2];
    356                         list($tickPositions,$minTickPositions) = self::GetTicksFromMinMax($aMin,$aMax,$type,$aMinor);
    357                         return array($fs,$tickPositions,$minTickPositions,$type);
    358                     }
    359                 }
    360             }
    361         }
     401        $diff = $aMax - $aMin;
     402        $spd = 3600*24;
     403        $spw = $spd*7;
     404        $spm = $spd*30;
     405        $spy = $spd*352;
     406
     407        if( self::$iUseWeeks )
     408            $w = 'W';
     409        else
     410            $w = 'd M';
     411
     412        // Decision table for suitable scales
     413        // First value: Main decision point
     414        // Second value: Array of formatting depending on divisor for wanted max number of ticks. <divisor><formatting><format-string>,..
     415        $tt = array(
     416            array($spw, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',-1,DSUTILS_DAY4,'d M')),
     417            array($spm, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M',
     418                              7,DSUTILS_WEEK1,$w,-1,DSUTILS_WEEK2,$w)),
     419            array($spy, array(1,DSUTILS_DAY1,'d M',2,DSUTILS_DAY2,'d M',4,DSUTILS_DAY4,'d M',
     420                              7,DSUTILS_WEEK1,$w,14,DSUTILS_WEEK2,$w,
     421                              30,DSUTILS_MONTH1,'M',60,DSUTILS_MONTH2,'M',-1,DSUTILS_MONTH3,'M')),
     422            array(-1, array(30,DSUTILS_MONTH1,'M-Y',60,DSUTILS_MONTH2,'M-Y',90,DSUTILS_MONTH3,'M-Y',
     423                            180,DSUTILS_MONTH6,'M-Y',352,DSUTILS_YEAR1,'Y',704,DSUTILS_YEAR2,'Y',-1,DSUTILS_YEAR5,'Y')));
     424
     425        $ntt = count($tt);
     426        $nd = floor($diff/$spd);
     427        for($i=0; $i < $ntt; ++$i ) {
     428            if( $diff <= $tt[$i][0] || $i==$ntt-1) {
     429                $t = $tt[$i][1];
     430                $n = count($t)/3;
     431                for( $j=0; $j < $n; ++$j ) {
     432                    if( $nd/$t[3*$j] <= $aMaxTicks || $j==$n-1) {
     433                        $type = $t[3*$j+1];
     434                        $fs = $t[3*$j+2];
     435                        list($tickPositions,$minTickPositions) = self::GetTicksFromMinMax($aMin,$aMax,$type,$aMinor);
     436                        return array($fs,$tickPositions,$minTickPositions,$type);
     437                    }
     438                }
     439            }
     440        }
    362441    }
    363442
    364443    static function GetTicksFromMinMax($aMin,$aMax,$aType,$aMinor=false,$aEndPoints=false) {
    365         self::$starthour = date('G',$aMin);
    366         self::$startmonth = date('n',$aMin);
    367         self::$startday = date('j',$aMin);
    368         self::$startyear = date('Y',$aMin);
    369         self::$endmonth = date('n',$aMax);
    370         self::$endyear = date('Y',$aMax);
    371         self::$endday = date('j',$aMax);
    372         self::$iMin = $aMin;
    373         self::$iMax = $aMax;
    374 
    375         if( $aType <= DSUTILS_MONTH6 ) {
    376             self::doMonthly($aType,$aMinor);
    377         }
    378         elseif( $aType <= DSUTILS_WEEK4 ) {
    379             self::doWeekly($aType,$aMinor);
    380         }
    381         elseif( $aType <= DSUTILS_DAY4 ) {
    382             self::doDaily($aType,$aMinor);
    383         }
    384         elseif( $aType <= DSUTILS_YEAR5 ) {
    385             self::doYearly($aType,$aMinor);
    386         }
    387         else {
    388             JpGraphError::RaiseL(24003);
    389         }
    390         // put a label at the very left data pos
    391         if( $aEndPoints ) {
    392             $tickPositions[$i++] = $aData[0];
    393         }
    394 
    395         // put a label at the very right data pos
    396         if( $aEndPoints ) {
    397             $tickPositions[$i] = $aData[$n-1];
    398         }
    399 
    400         return array(self::$tickPositions,self::$minTickPositions);
    401     }
     444        self::$starthour = date('G',$aMin);
     445        self::$startmonth = date('n',$aMin);
     446        self::$startday = date('j',$aMin);
     447        self::$startyear = date('Y',$aMin);
     448        self::$endmonth = date('n',$aMax);
     449        self::$endyear = date('Y',$aMax);
     450        self::$endday = date('j',$aMax);
     451        self::$iMin = $aMin;
     452        self::$iMax = $aMax;
     453
     454        if( $aType <= DSUTILS_MONTH6 ) {
     455            self::doMonthly($aType,$aMinor);
     456        }
     457        elseif( $aType <= DSUTILS_WEEK4 ) {
     458            self::doWeekly($aType,$aMinor);
     459        }
     460        elseif( $aType <= DSUTILS_DAY4 ) {
     461            self::doDaily($aType,$aMinor);
     462        }
     463        elseif( $aType <= DSUTILS_YEAR5 ) {
     464            self::doYearly($aType,$aMinor);
     465        }
     466        else {
     467            JpGraphError::RaiseL(24003);
     468        }
     469        // put a label at the very left data pos
     470        if( $aEndPoints ) {
     471            $tickPositions[$i++] = $aData[0];
     472        }
     473
     474        // put a label at the very right data pos
     475        if( $aEndPoints ) {
     476            $tickPositions[$i] = $aData[$n-1];
     477        }
     478
     479        return array(self::$tickPositions,self::$minTickPositions);
     480    }
     481
    402482}
    403483
     
    406486//=============================================================================
    407487Class ReadFileData {
     488
    408489    //----------------------------------------------------------------------------
    409490    // Desciption:
    410     // Read numeric data from a file.
    411     // Each value should be separated by either a new line or by a specified
     491    // Read numeric data from a file. 
     492    // Each value should be separated by either a new line or by a specified 
    412493    // separator character (default is ',').
    413     // Before returning the data each value is converted to a proper float
    414     // value. The routine is robust in the sense that non numeric data in the
     494    // Before returning the data each value is converted to a proper float 
     495    // value. The routine is robust in the sense that non numeric data in the 
    415496    // file will be discarded.
    416497    //
    417     // Returns:
     498    // Returns: 
    418499    // The number of data values read on success, FALSE on failure
    419500    //----------------------------------------------------------------------------
    420501    static function FromCSV($aFile,&$aData,$aSepChar=',',$aMaxLineLength=1024) {
    421         $rh = @fopen($aFile,'r');
    422         if( $rh === false ) {
    423                 return false;
    424         }
    425         $tmp = array();
    426         $lineofdata = fgetcsv($rh, 1000, ',');
    427         while ( $lineofdata !== FALSE) {
    428             $tmp = array_merge($tmp,$lineofdata);
    429             $lineofdata = fgetcsv($rh, $aMaxLineLength, $aSepChar);
    430         }
    431         fclose($rh);
    432 
    433         // Now make sure that all data is numeric. By default
    434         // all data is read as strings
    435         $n = count($tmp);
    436         $aData = array();
    437         $cnt=0;
    438         for($i=0; $i < $n; ++$i) {
    439             if( $tmp[$i] !== "" ) {
    440                 $aData[$cnt++] = floatval($tmp[$i]);
    441             }
    442         }
    443         return $cnt;
    444     }
    445 
    446     //----------------------------------------------------------------------------
    447     // Desciption:
    448     // Read numeric data from a file.
    449     // Each value should be separated by either a new line or by a specified
    450     // separator character (default is ',').
    451     // Before returning the data each value is converted to a proper float
    452     // value. The routine is robust in the sense that non numeric data in the
    453     // file will be discarded.
    454     //
    455     // Options:
    456     // 'separator'     => ',',
    457     // 'enclosure'     => '"',
    458     // 'readlength'    => 1024,
    459     // 'ignore_first'  => false,
    460     // 'first_as_key'  => false
    461     // 'escape'        => '\',   # PHP >= 5.3 only
    462     //
    463     // Returns:
    464     // The number of lines read on success, FALSE on failure
    465     //----------------------------------------------------------------------------
    466     static function FromCSV2($aFile, &$aData, $aOptions = array()) {
    467         $aDefaults = array(
    468             'separator'     => ',',
    469             'enclosure'     => chr(34),
    470             'escape'        => chr(92),
    471             'readlength'    => 1024,
    472             'ignore_first'  => false,
    473             'first_as_key'  => false
    474             );
    475 
    476         $aOptions = array_merge(
    477             $aDefaults, is_array($aOptions) ? $aOptions : array());
    478 
    479         if( $aOptions['first_as_key'] ) {
    480             $aOptions['ignore_first'] =  true;
    481         }
    482 
    483         $rh = @fopen($aFile, 'r');
    484 
    485         if( $rh === false ) {
    486             return false;
    487         }
    488 
    489         $aData  = array();
    490         $aLine  = fgetcsv($rh,
    491                           $aOptions['readlength'],
    492                           $aOptions['separator'],
    493                           $aOptions['enclosure']
    494                           /*, $aOptions['escape']     # PHP >= 5.3 only */
    495                           );
    496 
    497         // Use numeric array keys for the columns by default
    498         // If specified use first lines values as assoc keys instead
    499         $keys = array_keys($aLine);
    500         if( $aOptions['first_as_key'] ) {
    501             $keys = array_values($aLine);
    502         }
    503 
    504         $num_lines = 0;
    505         $num_cols  = count($aLine);
    506 
    507         while ($aLine !== false) {
    508             if( is_array($aLine) && count($aLine) != $num_cols ) {
    509                 JpGraphError::RaiseL(24004);
    510                 // 'ReadCSV2: Column count mismatch in %s line %d'
    511             }
    512 
    513             // fgetcsv returns NULL for empty lines
    514             if( !is_null($aLine) ) {
    515                 $num_lines++;
    516 
    517                 if( !($aOptions['ignore_first'] && $num_lines == 1) && is_numeric($aLine[0]) ) {
    518                     for( $i = 0; $i < $num_cols; $i++ ) {
    519                         $aData[ $keys[$i] ][] = floatval($aLine[$i]);
    520                     }
    521                 }
    522             }
    523 
    524             $aLine = fgetcsv($rh,
    525                              $aOptions['readlength'],
    526                              $aOptions['separator'],
    527                              $aOptions['enclosure']
    528                              /*, $aOptions['escape']     # PHP >= 5.3 only*/
    529                 );
    530         }
    531 
    532         fclose($rh);
    533 
    534         if( $aOptions['ignore_first'] ) {
    535             $num_lines--;
    536         }
    537 
    538         return $num_lines;
    539     }
    540 
    541     // Read data from two columns in a plain text file
    542     static function From2Col($aFile, $aCol1, $aCol2, $aSepChar=' ') {
    543         $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
    544         if( $lines === false ) {
    545                 return false;
    546         }
    547         $s = '/[\s]+/';
    548         if( $aSepChar == ',' ) {
    549                         $s = '/[\s]*,[\s]*/';
    550         }
    551         elseif( $aSepChar == ';' ) {
    552                         $s = '/[\s]*;[\s]*/';
    553         }
    554         foreach( $lines as $line => $datarow ) {
    555                 $split = preg_split($s,$datarow);
    556                 $aCol1[] = floatval(trim($split[0]));
    557                 $aCol2[] = floatval(trim($split[1]));
    558         }
    559 
    560         return count($lines);
    561     }
    562 
    563     // Read data from one columns in a plain text file
    564     static function From1Col($aFile, $aCol1) {
    565         $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
    566         if( $lines === false ) {
    567                 return false;
    568         }
    569         foreach( $lines as $line => $datarow ) {
    570                 $aCol1[] = floatval(trim($datarow));
    571         }
    572 
    573         return count($lines);
    574     }
    575 
    576     static function FromMatrix($aFile,$aSepChar=' ') {
    577         $lines = @file($aFile,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
    578         if( $lines === false ) {
    579                 return false;
    580         }
    581         $mat = array();
    582         $reg = '/'.$aSepChar.'/';
    583         foreach( $lines as $line => $datarow ) {
    584                 $row = preg_split($reg,trim($datarow));
    585                 foreach ($row as $key => $cell ) {
    586                         $row[$key] = floatval(trim($cell));
    587                 }
    588                 $mat[] = $row;
    589         }
    590         return $mat;
    591     }
    592 
    593 
     502        $rh = fopen($aFile,'r');
     503        if( $rh === false )
     504            return false;
     505        $tmp = array();
     506        $lineofdata = fgetcsv($rh, 1000, ',');
     507        while ( $lineofdata !== FALSE) {
     508            $tmp = array_merge($tmp,$lineofdata);
     509            $lineofdata = fgetcsv($rh, $aMaxLineLength, $aSepChar);
     510        }
     511        fclose($rh);
     512
     513        // Now make sure that all data is numeric. By default
     514        // all data is read as strings
     515        $n = count($tmp);
     516        $aData = array();
     517        $cnt=0;
     518        for($i=0; $i < $n; ++$i) {
     519            if( $tmp[$i] !== "" ) {
     520                $aData[$cnt++] = floatval($tmp[$i]);
     521            }
     522        }
     523        return $cnt;
     524    }
    594525}
    595526
    596 define('__LR_EPSILON', 1.0e-8);
    597 //=============================================================================
    598 // Class LinearRegression
    599 //=============================================================================
    600 class LinearRegression {
    601         private $ix=array(),$iy=array();
    602         private $ib=0, $ia=0;
    603         private $icalculated=false;
    604         public $iDet=0, $iCorr=0, $iStdErr=0;
    605 
    606         public function __construct($aDataX,$aDataY) {
    607                 if( count($aDataX) !== count($aDataY) ) {
    608                         JpGraph::Raise('LinearRegression: X and Y data array must be of equal length.');
    609                 }
    610                 $this->ix = $aDataX;
    611                 $this->iy = $aDataY;
    612         }
    613 
    614         public function Calc() {
    615 
    616                 $this->icalculated = true;
    617 
    618                 $n = count($this->ix);
    619                 $sx2 = 0 ;
    620                 $sy2 = 0 ;
    621                 $sxy = 0 ;
    622                 $sx = 0 ;
    623                 $sy = 0 ;
    624 
    625                 for( $i=0; $i < $n; ++$i ) {
    626                         $sx2 += $this->ix[$i] * $this->ix[$i];
    627                         $sy2 += $this->iy[$i] * $this->iy[$i];
    628                         $sxy += $this->ix[$i] * $this->iy[$i];
    629                         $sx += $this->ix[$i];
    630                         $sy += $this->iy[$i];
    631                 }
    632 
    633                 if( $n*$sx2 - $sx*$sx > __LR_EPSILON ) {
    634                         $this->ib = ($n*$sxy - $sx*$sy) / ( $n*$sx2 - $sx*$sx );
    635                         $this->ia = ( $sy - $this->ib*$sx ) / $n;
    636 
    637                         $sx = $this->ib * ( $sxy - $sx*$sy/$n );
    638                         $sy2 = $sy2 - $sy*$sy/$n;
    639                         $sy = $sy2 - $sx;
    640 
    641                         $this->iDet = $sx / $sy2;
    642                         $this->iCorr = sqrt($this->iDet);
    643                         if( $n > 2 ) {
    644                                 $this->iStdErr = sqrt( $sy / ($n-2) );
    645                         }
    646                         else {
    647                                 $this->iStdErr = NAN ;
    648                         }
    649                 }
    650                 else {
    651                         $this->ib = 0;
    652                         $this->ia = 0;
    653                 }
    654 
    655         }
    656 
    657         public function GetAB() {
    658                 if( $this->icalculated == false )
    659                         $this->Calc();
    660                 return array($this->ia, $this->ib);
    661         }
    662 
    663         public function GetStat() {
    664                 if( $this->icalculated == false )
    665                         $this->Calc();
    666                 return array($this->iStdErr, $this->iCorr, $this->iDet);
    667         }
    668 
    669         public function GetY($aMinX, $aMaxX, $aStep=1) {
    670                 if( $this->icalculated == false )
    671                         $this->Calc();
    672 
    673                 $yy = array();
    674                 $i = 0;
    675                 for( $x=$aMinX; $x <= $aMaxX; $x += $aStep ) {
    676                         $xx[$i  ] = $x;
    677                         $yy[$i++] = $this->ia + $this->ib * $x;
    678                 }
    679 
    680                 return array($xx,$yy);
    681         }
    682 
    683 }
    684 
    685527?>
  • trunk/client/modules/Elezioni/grafici/lang/de.inc.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3 // File:        DE.INC.PHP
     3// File:        DE.INC.PHP
    44// Description: German language file for error messages
    5 // Created:     2006-03-06
    6 // Author:      Timo Leopold (timo@leopold-hh.de)
    7 //              Johan Persson (ljp@localhost.nil)
    8 // Ver:         $Id: de.inc.php 1886 2009-10-01 23:30:16Z ljp $
     5// Created:     2006-03-06
     6// Author:      Timo Leopold (timo@leopold-hh.de)
     7// Ver:         $Id: de.inc.php 1017 2008-07-08 06:09:28Z ljp $
    98//
    109// Copyright (c)
     
    1918*/
    201910  => array('<table border="1"><tr><td style="color:darkred;font-size:1.2em;"><b>JpGraph Fehler:</b>
    21 HTTP header wurden bereits gesendet.<br>Fehler in der Datei <b>%s</b> in der Zeile <b>%d</b>.</td></tr><tr><td><b>ErklÀrung:</b><br>HTTP header wurden bereits zum Browser gesendet, wobei die Daten als Text gekennzeichnet wurden, bevor die Bibliothek die Chance hatte, seinen Bild-HTTP-Header zum Browser zu schicken. Dies verhindert, dass die Bibliothek Bilddaten zum Browser schicken kann (weil sie vom Browser als Text interpretiert wÃŒrden und daher nur Mist dargestellt wÃŒrde).<p>Wahrscheinlich steht Text im Skript bevor <i>Graph::Stroke()</i> aufgerufen wird. Wenn dieser Text zum Browser gesendet wird, nimmt dieser an, dass die gesamten Daten aus Text bestehen. Such nach irgendwelchem Text, auch nach Leerzeichen und ZeilenumbrÃŒchen, die eventuell bereits zum Browser gesendet wurden. <p>Zum Beispiel ist ein oft auftretender Fehler, eine Leerzeile am Anfang der Datei oder vor <i>Graph::Stroke()</i> zu lassen."<b>&lt;?php</b>".</td></tr></table>',2),
     20HTTP header wurden bereits gesendet.<br>Fehler in der Datei <b>%s</b> in der Zeile <b>%d</b>.</td></tr><tr><td><b>Erklärung:</b><br>HTTP header wurden bereits zum Browser gesendet, wobei die Daten als Text gekennzeichnet wurden, bevor die Bibliothek die Chance hatte, seinen Bild-HTTP-Header zum Browser zu schicken. Dies verhindert, dass die Bibliothek Bilddaten zum Browser schicken kann (weil sie vom Browser als Text interpretiert würden und daher nur Mist dargestellt würde).<p>Wahrscheinlich steht Text im Skript bevor <i>Graph::Stroke()</i> aufgerufen wird. Wenn dieser Text zum Browser gesendet wird, nimmt dieser an, dass die gesamten Daten aus Text bestehen. Such nach irgendwelchem Text, auch nach Leerzeichen und Zeilenumbrüchen, die eventuell bereits zum Browser gesendet wurden. <p>Zum Beispiel ist ein oft auftretender Fehler, eine Leerzeile am Anfang der Datei oder vor <i>Graph::Stroke()</i> zu lassen."<b>&lt;?php</b>".</td></tr></table>',2),
    2221
    2322/*
    2423** Setup Fehler
    2524*/
    26 11 => array('Es wurde kein Pfad fÃŒr CACHE_DIR angegeben. Bitte gib einen Pfad CACHE_DIR in der Datei jpg-config.inc an.',0),
    27 12 => array('Es wurde kein Pfad fÃŒr TTF_DIR angegeben und der Pfad kann nicht automatisch ermittelt werden. Bitte gib den Pfad in der Datei jpg-config.inc an.',0),
     2511 => array('Es wurde kein Pfad für CACHE_DIR angegeben. Bitte gib einen Pfad CACHE_DIR in der Datei jpg-config.inc an.',0),
     2612 => array('Es wurde kein Pfad für TTF_DIR angegeben und der Pfad kann nicht automatisch ermittelt werden. Bitte gib den Pfad in der Datei jpg-config.inc an.',0),
    282713 => array('The installed PHP version (%s) is not compatible with this release of the library. The library requires at least PHP version %s',2),
    2928
     
    35342002 => array('Unbekannte Vorlage im Aufruf von BarPlot::SetPattern().',0),
    36352003 => array('Anzahl der X- und Y-Koordinaten sind nicht identisch. Anzahl der X-Koordinaten: %d; Anzahl der Y-Koordinaten: %d.',2),
    37 2004 => array('Alle Werte fÃŒr ein Balkendiagramm (barplot) mÃŒssen numerisch sein. Du hast den Wert nr [%d] == %s angegeben.',2),
    38 2005 => array('Du hast einen leeren Vektor fÃŒr die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0),
    39 2006 => array('Unbekannte Position fÃŒr die Werte der Balken: %s.',1),
     362004 => array('Alle Werte für ein Balkendiagramm (barplot) müssen numerisch sein. Du hast den Wert nr [%d] == %s angegeben.',2),
     372005 => array('Du hast einen leeren Vektor für die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0),
     382006 => array('Unbekannte Position für die Werte der Balken: %s.',1),
    40392007 => array('Kann GroupBarPlot nicht aus einem leeren Vektor erzeugen.',0),
    41402008 => array('GroupBarPlot Element nbr %d wurde nicht definiert oder ist leer.',0),
     
    44432011 => array('AccBarPlot-Element nbr %d wurde nicht definiert oder ist leer.',1),
    45442012 => array('Eins der Objekte, das an AccBar weitergegeben wurde ist kein Balkendiagramm (barplot). Versichere Dich, dass Du den AccBar-Plot aus einem Vektor von Balkendiagrammen (barplot) erzeugst. (Class=%s)',1),
    46 2013 => array('Du hast einen leeren Vektor fÃŒr die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0),
     452013 => array('Du hast einen leeren Vektor für die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0),
    47462014 => array('Die Anzahl der Datenpunkte jeder Datenreihe in AccBarPlot muss gleich sein.',0),
    48472015 => array('Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-coordinates',0),
     
    5352*/
    5453
    55 3001 => array('Es ist nur möglich, entweder SetDateAlign() oder SetTimeAlign() zu benutzen, nicht beides!',0),
     543001 => array('Es ist nur möglich, entweder SetDateAlign() oder SetTimeAlign() zu benutzen, nicht beides!',0),
    5655
    5756/*
     
    6564*/
    6665
    67 5001 => array('Unbekannte Flaggen-Größe (%d).',1),
     665001 => array('Unbekannte Flaggen-Größe (%d).',1),
    68675002 => array('Der Flaggen-Index %s existiert nicht.',1),
    69 5003 => array('Es wurde eine ungÃŒltige Ordnungszahl (%d) fÃŒr den Flaggen-Index angegeben.',1),
     685003 => array('Es wurde eine ungültige Ordnungszahl (%d) für den Flaggen-Index angegeben.',1),
    70695004 => array('Der Landesname %s hat kein korrespondierendes Flaggenbild. Die Flagge mag existieren, abr eventuell unter einem anderen Namen, z.B. versuche "united states" statt "usa".',1),
    7170
     
    7574*/
    7675
    77 6001 => array('Interner Fehler. Die Höhe fÃŒr ActivityTitles ist < 0.',0),
    78 6002 => array('Es dÃŒrfen keine negativen Werte fÃŒr die Gantt-Diagramm-Dimensionen angegeben werden. Verwende 0, wenn die Dimensionen automatisch ermittelt werden sollen.',0),
    79 6003 => array('UngÃŒltiges Format fÃŒr den Bedingungs-Parameter bei Index=%d in CreateSimple(). Der Parameter muss bei index 0 starten und Vektoren in der Form (Row,Constrain-To,Constrain-Type) enthalten.',1),
    80 6004 => array('UngÃŒltiges Format fÃŒr den Fortschritts-Parameter bei Index=%d in CreateSimple(). Der Parameter muss bei Index 0 starten und Vektoren in der Form (Row,Progress) enthalten.',1),
     766001 => array('Interner Fehler. Die Höhe für ActivityTitles ist < 0.',0),
     776002 => array('Es dürfen keine negativen Werte für die Gantt-Diagramm-Dimensionen angegeben werden. Verwende 0, wenn die Dimensionen automatisch ermittelt werden sollen.',0),
     786003 => array('Ungültiges Format für den Bedingungs-Parameter bei Index=%d in CreateSimple(). Der Parameter muss bei index 0 starten und Vektoren in der Form (Row,Constrain-To,Constrain-Type) enthalten.',1),
     796004 => array('Ungültiges Format für den Fortschritts-Parameter bei Index=%d in CreateSimple(). Der Parameter muss bei Index 0 starten und Vektoren in der Form (Row,Progress) enthalten.',1),
    81806005 => array('SetScale() ist nicht sinnvoll bei Gantt-Diagrammen.',0),
    82 6006 => array('Das Gantt-Diagramm kann nicht automatisch skaliert werden. Es existieren keine AktivitÀten mit Termin. [GetBarMinMax() start >= n]',0),
    83 6007 => array('PlausibiltÀtsprÃŒfung fÃŒr die automatische Gantt-Diagramm-Größe schlug fehl. Entweder die Breite (=%d) oder die Höhe (=%d) ist größer als MAX_GANTTIMG_SIZE. Dies kann möglicherweise durch einen falschen Wert bei einer AktivitÀt hervorgerufen worden sein.',2),
    84 6008 => array('Du hast eine Bedingung angegeben von Reihe=%d bis Reihe=%d, die keine AktivitÀt hat.',2),
     816006 => array('Das Gantt-Diagramm kann nicht automatisch skaliert werden. Es existieren keine Aktivitäten mit Termin. [GetBarMinMax() start >= n]',0),
     826007 => array('Plausibiltätsprüfung für die automatische Gantt-Diagramm-Größe schlug fehl. Entweder die Breite (=%d) oder die Höhe (=%d) ist größer als MAX_GANTTIMG_SIZE. Dies kann möglicherweise durch einen falschen Wert bei einer Aktivität hervorgerufen worden sein.',2),
     836008 => array('Du hast eine Bedingung angegeben von Reihe=%d bis Reihe=%d, die keine Aktivität hat.',2),
    85846009 => array('Unbekannter Bedingungstyp von Reihe=%d bis Reihe=%d',2),
    86 6010 => array('UngÃŒltiger Icon-Index fÃŒr das eingebaute Gantt-Icon [%d]',1),
    87 6011 => array('Argument fÃŒr IconImage muss entweder ein String oder ein Integer sein.',0),
     856010 => array('Ungültiger Icon-Index für das eingebaute Gantt-Icon [%d]',1),
     866011 => array('Argument für IconImage muss entweder ein String oder ein Integer sein.',0),
    88876012 => array('Unbekannter Typ bei der Gantt-Objekt-Title-Definition.',0),
    89 6015 => array('UngÃŒltige vertikale Position %d',1),
    90 6016 => array('Der eingegebene Datums-String (%s) fÃŒr eine Gantt-AktivitÀt kann nicht interpretiert werden. Versichere Dich, dass es ein gÃŒltiger Datumsstring ist, z.B. 2005-04-23 13:30',1),
     886015 => array('Ungültige vertikale Position %d',1),
     896016 => array('Der eingegebene Datums-String (%s) für eine Gantt-Aktivität kann nicht interpretiert werden. Versichere Dich, dass es ein gültiger Datumsstring ist, z.B. 2005-04-23 13:30',1),
    91906017 => array('Unbekannter Datumstyp in GanttScale (%s).',1),
    92 6018 => array('Intervall fÃŒr Minuten muss ein gerader Teiler einer Stunde sein, z.B. 1,5,10,12,15,20,30, etc. Du hast ein Intervall von %d Minuten angegeben.',1),
    93 6019 => array('Die vorhandene Breite (%d) fÃŒr die Minuten ist zu klein, um angezeigt zu werden. Bitte benutze die automatische Größenermittlung oder vergrößere die Breite des Diagramms.',1),
    94 6020 => array('Das Intervall fÃŒr die Stunden muss ein gerader Teiler eines Tages sein, z.B. 0:30, 1:00, 1:30, 4:00, etc. Du hast ein Intervall von %d eingegeben.',1),
    95 6021 => array('Unbekanntes Format fÃŒr die Woche.',0),
     916018 => array('Intervall für Minuten muss ein gerader Teiler einer Stunde sein, z.B. 1,5,10,12,15,20,30, etc. Du hast ein Intervall von %d Minuten angegeben.',1),
     926019 => array('Die vorhandene Breite (%d) für die Minuten ist zu klein, um angezeigt zu werden. Bitte benutze die automatische Größenermittlung oder vergrößere die Breite des Diagramms.',1),
     936020 => array('Das Intervall für die Stunden muss ein gerader Teiler eines Tages sein, z.B. 0:30, 1:00, 1:30, 4:00, etc. Du hast ein Intervall von %d eingegeben.',1),
     946021 => array('Unbekanntes Format für die Woche.',0),
    96956022 => array('Die Gantt-Skala wurde nicht eingegeben.',0),
    97966023 => array('Wenn Du sowohl Stunden als auch Minuten anzeigen lassen willst, muss das Stunden-Interval gleich 1 sein (anderenfalls ist es nicht sinnvoll, Minuten anzeigen zu lassen).',0),
     
    99986025 => array('Der CSIM-Alt-Text muss als String angegeben werden. Der Beginn des Alt-Textes ist: %d',1),
    100996027 => array('Der Fortschrittswert muss im Bereich [0, 1] liegen.',0),
    101 6028 => array('Die eingegebene Höhe (%d) fÃŒr GanttBar ist nicht im zulÀssigen Bereich.',1),
    102 6029 => array('Der Offset fÃŒr die vertikale Linie muss im Bereich [0,1] sein.',0),
    103 6030 => array('Unbekannte Pfeilrichtung fÃŒr eine Verbindung.',0),
    104 6031 => array('Unbekannter Pfeiltyp fÃŒr eine Verbindung.',0),
    105 6032 => array('Interner Fehler: Unbekannter Pfadtyp (=%d) fÃŒr eine Verbindung.',1),
    106 6033 => array('Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)',0),
     1006028 => array('Die eingegebene Höhe (%d) für GanttBar ist nicht im zulässigen Bereich.',1),
     1016029 => array('Der Offset für die vertikale Linie muss im Bereich [0,1] sein.',0),
     1026030 => array('Unbekannte Pfeilrichtung für eine Verbindung.',0),
     1036031 => array('Unbekannter Pfeiltyp für eine Verbindung.',0),
     1046032 => array('Interner Fehler: Unbekannter Pfadtyp (=%d) für eine Verbindung.',1),
    107105
    108106/*
     
    116114*/
    117115
    118 8001 => array('Der Mix-Wert fÃŒr das Icon muss zwischen 0 und 100 sein.',0),
    119 8002 => array('Die Ankerposition fÃŒr Icons muss entweder "top", "bottom", "left", "right" oder "center" sein.',0),
    120 8003 => array('Es ist nicht möglich, gleichzeitig ein Bild und eine Landesflagge fÃŒr dasselbe Icon zu definieren',0),
    121 8004 => array('Wenn Du Landesflaggen benutzen willst, musst Du die Datei "jpgraph_flags.php" hinzufÃŒgen (per include).',0),
     1168001 => array('Der Mix-Wert für das Icon muss zwischen 0 und 100 sein.',0),
     1178002 => array('Die Ankerposition für Icons muss entweder "top", "bottom", "left", "right" oder "center" sein.',0),
     1188003 => array('Es ist nicht möglich, gleichzeitig ein Bild und eine Landesflagge für dasselbe Icon zu definieren',0),
     1198004 => array('Wenn Du Landesflaggen benutzen willst, musst Du die Datei "jpgraph_flags.php" hinzufügen (per include).',0),
    122120
    123121/*
     
    125123*/
    126124
    127 9001 => array('Der Wert fÃŒr die Bildtransformation ist außerhalb des zulÀssigen Bereichs. Der verschwindende Punkt am Horizont muss als Wert zwischen 0 und 1 angegeben werden.',0),
     1259001 => array('Der Wert für die Bildtransformation ist außerhalb des zulässigen Bereichs. Der verschwindende Punkt am Horizont muss als Wert zwischen 0 und 1 angegeben werden.',0),
    128126
    129127/*
     
    132130
    13313110001 => array('Die Methode LinePlot::SetFilled() sollte nicht mehr benutzt werden. Benutze lieber SetFillColor()',0),
    134 10002 => array('Der Plot ist zu kompliziert fÃŒr FastLineStroke. Benutze lieber den StandardStroke()',0),
     13210002 => array('Der Plot ist zu kompliziert für FastLineStroke. Benutze lieber den StandardStroke()',0),
    13513310003 => array('Each plot in an accumulated lineplot must have the same number of data points.',0),
    136134/*
     
    139137
    14013811001 => array('Deine Daten enthalten nicht-numerische Werte.',0),
    141 11002 => array('Negative Werte können nicht fÃŒr logarithmische Achsen verwendet werden.',0),
     13911002 => array('Negative Werte können nicht für logarithmische Achsen verwendet werden.',0),
    14214011003 => array('Deine Daten enthalten nicht-numerische Werte.',0),
    143 11004 => array('Skalierungsfehler fÃŒr die logarithmische Achse. Es gibt ein Problem mit den Daten der Achse. Der größte Wert muss größer sein als Null. Es ist mathematisch nicht möglich, einen Wert gleich Null in der Skala zu haben.',0),
    144 11005 => array('Das Tick-Intervall fÃŒr die logarithmische Achse ist nicht definiert. Lösche jeden Aufruf von SetTextLabelStart() oder SetTextTickInterval() bei der logarithmischen Achse.',0),
     14111004 => array('Skalierungsfehler für die logarithmische Achse. Es gibt ein Problem mit den Daten der Achse. Der größte Wert muss größer sein als Null. Es ist mathematisch nicht möglich, einen Wert gleich Null in der Skala zu haben.',0),
     14211005 => array('Das Tick-Intervall für die logarithmische Achse ist nicht definiert. Lösche jeden Aufruf von SetTextLabelStart() oder SetTextTickInterval() bei der logarithmischen Achse.',0),
    145143
    146144/*
     
    148146*/
    149147
    150 12001 => array("Du benutzt GD 2.x und versuchst ein Nicht-Truecolor-Bild als Hintergrundbild zu benutzen. Um Hintergrundbilder mit GD 2.x zu benutzen, ist es notwendig Truecolor zu aktivieren, indem die USE_TRUECOLOR-Konstante auf TRUE gesetzt wird. Wegen eines Bugs in GD 2.0.1 ist die QualitÀt der Truetype-Schriften sehr schlecht, wenn man Truetype-Schriften mit Truecolor-Bildern verwendet.",0),
    151 12002 => array('UngÃŒltiger Dateiname fÃŒr MGraph::SetBackgroundImage() : %s. Die Datei muss eine gÃŒltige Dateierweiterung haben (jpg,gif,png), wenn die automatische Typerkennung verwendet wird.',1),
    152 12003 => array('Unbekannte Dateierweiterung (%s) in MGraph::SetBackgroundImage() fÃŒr Dateiname: %s',2),
    153 12004 => array('Das Bildformat des Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstÃŒtzt. ',1),
     14812001 => array("Du benutzt GD 2.x und versuchst ein Nicht-Truecolor-Bild als Hintergrundbild zu benutzen. Um Hintergrundbilder mit GD 2.x zu benutzen, ist es notwendig Truecolor zu aktivieren, indem die USE_TRUECOLOR-Konstante auf TRUE gesetzt wird. Wegen eines Bugs in GD 2.0.1 ist die Qualität der Truetype-Schriften sehr schlecht, wenn man Truetype-Schriften mit Truecolor-Bildern verwendet.",0),
     14912002 => array('Ungültiger Dateiname für MGraph::SetBackgroundImage() : %s. Die Datei muss eine gültige Dateierweiterung haben (jpg,gif,png), wenn die automatische Typerkennung verwendet wird.',1),
     15012003 => array('Unbekannte Dateierweiterung (%s) in MGraph::SetBackgroundImage() für Dateiname: %s',2),
     15112004 => array('Das Bildformat des Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstützt. ',1),
    15415212005 => array('Das Hintergrundbild kann nicht gelesen werden: %s',1),
    155 12006 => array('Es wurden ungÃŒltige Größen fÃŒr Breite oder Höhe beim Erstellen des Bildes angegeben, (Breite=%d, Höhe=%d)',2),
    156 12007 => array('Das Argument fÃŒr MGraph::Add() ist nicht gÃŒltig fÃŒr GD.',0),
    157 12008 => array('Deine PHP- (und GD-lib-) Installation scheint keine bekannten Bildformate zu unterstÃŒtzen.',0),
    158 12009 => array('Deine PHP-Installation unterstÃŒtzt das gewÀhlte Bildformat nicht: %s',1),
    159 12010 => array('Es konnte kein Bild als Datei %s erzeugt werden. ÜberprÃŒfe, ob Du die entsprechenden Schreibrechte im aktuellen Verzeichnis hast.',1),
    160 12011 => array('Es konnte kein Truecolor-Bild erzeugt werden. ÜberprÃŒfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0),
    161 12012 => array('Es konnte kein Bild erzeugt werden. ÜberprÃŒfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0),
     15312006 => array('Es wurden ungültige Größen für Breite oder Höhe beim Erstellen des Bildes angegeben, (Breite=%d, Höhe=%d)',2),
     15412007 => array('Das Argument für MGraph::Add() ist nicht gültig für GD.',0),
     15512008 => array('Deine PHP- (und GD-lib-) Installation scheint keine bekannten Bildformate zu unterstützen.',0),
     15612009 => array('Deine PHP-Installation unterstützt das gewählte Bildformat nicht: %s',1),
     15712010 => array('Es konnte kein Bild als Datei %s erzeugt werden. Überprüfe, ob Du die entsprechenden Schreibrechte im aktuellen Verzeichnis hast.',1),
     15812011 => array('Es konnte kein Truecolor-Bild erzeugt werden. Überprüfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0),
     15912012 => array('Es konnte kein Bild erzeugt werden. Überprüfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0),
    162160
    163161/*
     
    165163*/
    166164
    167 14001 => array('Pie3D::ShowBorder(). Missbilligte Funktion. Benutze Pie3D::SetEdge(), um die Ecken der TortenstÃŒcke zu kontrollieren.',0),
     16514001 => array('Pie3D::ShowBorder(). Missbilligte Funktion. Benutze Pie3D::SetEdge(), um die Ecken der Tortenstücke zu kontrollieren.',0),
    16816614002 => array('PiePlot3D::SetAngle() 3D-Torten-Projektionswinkel muss zwischen 5 und 85 Grad sein.',0),
    16916714003 => array('Interne Festlegung schlug fehl. Pie3D::Pie3DSlice',0),
    170 14004 => array('TortenstÃŒck-Startwinkel muss zwischen 0 und 360 Grad sein.',0),
    171 14005 => array('Pie3D Interner Fehler: Versuch, zweimal zu umhÃŒllen bei der Suche nach dem Startindex.',0,),
    172 14006 => array('Pie3D Interner Fehler: Z-Sortier-Algorithmus fÃŒr 3D-Tortendiagramme funktioniert nicht einwandfrei (2). Versuch, zweimal zu umhÃŒllen beim Erstellen des Bildes.',0),
    173 14007 => array('Die Breite fÃŒr das 3D-Tortendiagramm ist 0. Gib eine Breite > 0 an.',0),
     16814004 => array('Tortenstück-Startwinkel muss zwischen 0 und 360 Grad sein.',0),
     16914005 => array('Pie3D Interner Fehler: Versuch, zweimal zu umhüllen bei der Suche nach dem Startindex.',0,),
     17014006 => array('Pie3D Interner Fehler: Z-Sortier-Algorithmus für 3D-Tortendiagramme funktioniert nicht einwandfrei (2). Versuch, zweimal zu umhüllen beim Erstellen des Bildes.',0),
     17114007 => array('Die Breite für das 3D-Tortendiagramm ist 0. Gib eine Breite > 0 an.',0),
    174172
    175173/*
     
    178176
    17917715001 => array('PiePLot::SetTheme() Unbekannter Stil: %s',1),
    180 15002 => array('Argument fÃŒr PiePlot::ExplodeSlice() muss ein Integer-Wert sein',0),
    181 15003 => array('Argument fÃŒr PiePlot::Explode() muss ein Vektor mit Integer-Werten sein.',0),
    182 15004 => array('TortenstÃŒck-Startwinkel muss zwischen 0 und 360 Grad sein.',0),
     17815002 => array('Argument für PiePlot::ExplodeSlice() muss ein Integer-Wert sein',0),
     17915003 => array('Argument für PiePlot::Explode() muss ein Vektor mit Integer-Werten sein.',0),
     18015004 => array('Tortenstück-Startwinkel muss zwischen 0 und 360 Grad sein.',0),
    18318115005 => array('PiePlot::SetFont() sollte nicht mehr verwendet werden. Benutze stattdessen PiePlot->value->SetFont().',0),
    184 15006 => array('PiePlot::SetSize() Radius fÃŒr Tortendiagramm muss entweder als Bruch [0, 0.5] der Bildgröße oder als Absoluwert in Pixel im Bereich [10, 1000] angegeben werden.',0),
     18215006 => array('PiePlot::SetSize() Radius für Tortendiagramm muss entweder als Bruch [0, 0.5] der Bildgröße oder als Absoluwert in Pixel im Bereich [10, 1000] angegeben werden.',0),
    18518315007 => array('PiePlot::SetFontColor() sollte nicht mehr verwendet werden. Benutze stattdessen PiePlot->value->SetColor()..',0),
    186 15008 => array('PiePlot::SetLabelType() der Typ fÃŒr Tortendiagramme muss entweder 0 or 1 sein (nicht %d).',1),
    187 15009 => array('UngÃŒltiges Tortendiagramm. Die Summe aller Daten ist Null.',0),
     18415008 => array('PiePlot::SetLabelType() der Typ für Tortendiagramme muss entweder 0 or 1 sein (nicht %d).',1),
     18515009 => array('Ungültiges Tortendiagramm. Die Summe aller Daten ist Null.',0),
    18818615010 => array('Die Summe aller Daten ist Null.',0),
    189 15011 => array('Um Bildtransformationen benutzen zu können, muss die Datei jpgraph_imgtrans.php eingefÃŒgt werden (per include).',0), // @todo translate into German
    190 15012 => array('PiePlot::SetTheme() is no longer recommended. Use PieGraph::SetTheme()',0),
     18715011 => array('Um Bildtransformationen benutzen zu können, muss die Datei jpgraph_imgtrans.php eingefügt werden (per include).',0),
    191188
    192189/*
     
    194191*/
    195192
    196 16001 => array('Die Dichte fÃŒr das Pattern muss zwischen 1 und 100 sein. (Du hast %f eingegeben)',1),
    197 16002 => array('Es wurde keine Position fÃŒr das Pattern angegeben.',0),
     19316001 => array('Die Dichte für das Pattern muss zwischen 1 und 100 sein. (Du hast %f eingegeben)',1),
     19416002 => array('Es wurde keine Position für das Pattern angegeben.',0),
    19819516003 => array('Unbekannte Pattern-Definition (%d)',0),
    199 16004 => array('Der Mindeswert fÃŒr das PlotBand ist größer als der Maximalwert. Bitte korrigiere dies!',0),
     19616004 => array('Der Mindeswert für das PlotBand ist größer als der Maximalwert. Bitte korrigiere dies!',0),
    200197
    201198
     
    204201*/
    205202
    206 17001 => array('PolarPlots mÃŒssen eine gerade Anzahl von Datenpunkten haben. Jeder Datenpunkt ist ein Tupel (Winkel, Radius).',0),
    207 17002 => array('Unbekannte Ausrichtung fÃŒr X-Achsen-Titel. (%s)',1),
    208 //17003 => array('Set90AndMargin() wird fÃŒr PolarGraph nicht unterstÃŒtzt.',0),
    209 17004 => array('Unbekannter Achsentyp fÃŒr PolarGraph. Er muss entweder \'lin\' oder \'log\' sein.',0),
     20317001 => array('PolarPlots müssen eine gerade Anzahl von Datenpunkten haben. Jeder Datenpunkt ist ein Tupel (Winkel, Radius).',0),
     20417002 => array('Unbekannte Ausrichtung für X-Achsen-Titel. (%s)',1),
     205//17003 => array('Set90AndMargin() wird für PolarGraph nicht unterstützt.',0),
     20617004 => array('Unbekannter Achsentyp für PolarGraph. Er muss entweder \'lin\' oder \'log\' sein.',0),
    210207
    211208/*
     
    213210*/
    214211
    215 18001 => array('ClientSideImageMaps werden fÃŒr RadarPlots nicht unterstÃŒtzt.',0),
     21218001 => array('ClientSideImageMaps werden für RadarPlots nicht unterstützt.',0),
    21621318002 => array('RadarGraph::SupressTickMarks() sollte nicht mehr verwendet werden. Benutze stattdessen HideTickMarks().',0),
    217 18003 => array('UngÃŒltiger Achsentyp fÃŒr RadarPlot (%s). Er muss entweder \'lin\' oder \'log\' sein.',1),
    218 18004 => array('Die RadarPlot-Größe muss zwischen 0.1 und 1 sein. (Dein Wert=%f)',1),
    219 18005 => array('RadarPlot: nicht unterstÃŒtzte Tick-Dichte: %d',1),
     21418003 => array('Ungültiger Achsentyp für RadarPlot (%s). Er muss entweder \'lin\' oder \'log\' sein.',1),
     21518004 => array('Die RadarPlot-Größe muss zwischen 0.1 und 1 sein. (Dein Wert=%f)',1),
     21618005 => array('RadarPlot: nicht unterstützte Tick-Dichte: %d',1),
    22021718006 => array('Minimum Daten %f (RadarPlots sollten nur verwendet werden, wenn alle Datenpunkte einen Wert > 0 haben).',1),
    22121818007 => array('Die Anzahl der Titel entspricht nicht der Anzahl der Datenpunkte.',0),
     
    227224
    22822519001 => array('Spline: Anzahl der X- und Y-Koordinaten muss gleich sein.',0),
    229 19002 => array('UngÃŒltige Dateneingabe fÃŒr Spline. Zwei oder mehr aufeinanderfolgende X-Werte sind identisch. Jeder eigegebene X-Wert muss unterschiedlich sein, weil vom mathematischen Standpunkt ein Eins-zu-Eins-Mapping vorliegen muss, d.h. jeder X-Wert korrespondiert mit exakt einem Y-Wert.',0),
     22619002 => array('Ungültige Dateneingabe für Spline. Zwei oder mehr aufeinanderfolgende X-Werte sind identisch. Jeder eigegebene X-Wert muss unterschiedlich sein, weil vom mathematischen Standpunkt ein Eins-zu-Eins-Mapping vorliegen muss, d.h. jeder X-Wert korrespondiert mit exakt einem Y-Wert.',0),
    23022719003 => array('Bezier: Anzahl der X- und Y-Koordinaten muss gleich sein.',0),
    231228
     
    234231*/
    235232
    236 20001 => array('Fieldplots mÃŒssen die gleiche Anzahl von X und Y Datenpunkten haben.',0),
    237 20002 => array('Bei Fieldplots muss ein Winkel fÃŒr jeden X und Y Datenpunkt angegeben werden.',0),
    238 20003 => array('Scatterplots mÃŒssen die gleiche Anzahl von X- und Y-Datenpunkten haben.',0),
     23320001 => array('Fieldplots müssen die gleiche Anzahl von X und Y Datenpunkten haben.',0),
     23420002 => array('Bei Fieldplots muss ein Winkel für jeden X und Y Datenpunkt angegeben werden.',0),
     23520003 => array('Scatterplots müssen die gleiche Anzahl von X- und Y-Datenpunkten haben.',0),
    239236
    240237/*
     
    242239*/
    243240
    244 21001 => array('Die Anzahl der Datenwerte fÃŒr Stock-Charts mÃŒssen ein Mehrfaches von %d Datenpunkten sein.',1),
     24121001 => array('Die Anzahl der Datenwerte für Stock-Charts müssen ein Mehrfaches von %d Datenpunkten sein.',1),
    245242
    246243/*
     
    249246
    25024723001 => array('Der Marker "%s" existiert nicht in der Farbe: %d',2),
    251 23002 => array('Der Farb-Index ist zu hoch fÃŒr den Marker "%s"',1),
     24823002 => array('Der Farb-Index ist zu hoch für den Marker "%s"',1),
    25224923003 => array('Ein Dateiname muss angegeben werden, wenn Du den Marker-Typ auf MARK_IMG setzt.',0),
    253250
     
    25925624002 => array('FuncGenerator : Syntax-Fehler in der Funktionsdefinition ',0),
    26025724003 => array('DateScaleUtils: Unknown tick type specified in call to GetTicks()',0),
    261 24004 => array('ReadCSV2: Die anzahl der spalten fehler in %s reihe %d',2),
     258
    262259/*
    263260**  jpgraph
    264261*/
    265262
    266 25001 => array('Diese PHP-Installation ist nicht mit der GD-Bibliothek kompiliert. Bitte kompiliere PHP mit GD-UnterstÃŒtzung neu, damit JpGraph funktioniert. (Weder die Funktion imagetypes() noch imagecreatefromstring() existiert!)',0),
    267 25002 => array('Diese PHP-Installation scheint nicht die benötigte GD-Bibliothek zu unterstÃŒtzen. Bitte schau in der PHP-Dokumentation nach, wie man die GD-Bibliothek installiert und aktiviert.',0),
     26325001 => array('Diese PHP-Installation ist nicht mit der GD-Bibliothek kompiliert. Bitte kompiliere PHP mit GD-Unterstützung neu, damit JpGraph funktioniert. (Weder die Funktion imagetypes() noch imagecreatefromstring() existiert!)',0),
     26425002 => array('Diese PHP-Installation scheint nicht die benötigte GD-Bibliothek zu unterstützen. Bitte schau in der PHP-Dokumentation nach, wie man die GD-Bibliothek installiert und aktiviert.',0),
    26826525003 => array('Genereller PHP Fehler : Bei %s:%d : %s',3),
    26926625004 => array('Genereller PHP Fehler : %s ',1),
    27026725005 => array('PHP_SELF, die PHP-Global-Variable kann nicht ermittelt werden. PHP kann nicht von der Kommandozeile gestartet werden, wenn der Cache oder die Bilddateien automatisch benannt werden sollen.',0),
    271 25006 => array('Die Benutzung der FF_CHINESE (FF_BIG5) Schriftfamilie benötigt die iconv() Funktion in Deiner PHP-Konfiguration. Dies wird nicht defaultmÀßig in PHP kompiliert (benötigt "--width-iconv" bei der Konfiguration).',0),
    272 25007 => array('Du versuchst das lokale (%s) zu verwenden, was von Deiner PHP-Installation nicht unterstÃŒtzt wird. Hinweis: Benutze \'\', um das defaultmÀßige Lokale fÃŒr diese geographische Region festzulegen.',1),
    273 25008 => array('Die Bild-Breite und Höhe in Graph::Graph() mÃŒssen numerisch sein',0),
     26825006 => array('Die Benutzung der FF_CHINESE (FF_BIG5) Schriftfamilie benötigt die iconv() Funktion in Deiner PHP-Konfiguration. Dies wird nicht defaultmäßig in PHP kompiliert (benötigt "--width-iconv" bei der Konfiguration).',0),
     26925007 => array('Du versuchst das lokale (%s) zu verwenden, was von Deiner PHP-Installation nicht unterstützt wird. Hinweis: Benutze \'\', um das defaultmäßige Lokale für diese geographische Region festzulegen.',1),
     27025008 => array('Die Bild-Breite und Höhe in Graph::Graph() müssen numerisch sein',0),
    27427125009 => array('Die Skalierung der Achsen muss angegeben werden mit Graph::SetScale()',0),
    275272
    276 25010 => array('Graph::Add() Du hast versucht, einen leeren Plot zum Graph hinzuzufÃŒgen.',0),
    277 25011 => array('Graph::AddY2() Du hast versucht, einen leeren Plot zum Graph hinzuzufÃŒgen.',0),
    278 25012 => array('Graph::AddYN() Du hast versucht, einen leeren Plot zum Graph hinzuzufÃŒgen.',0),
    279 25013 => array('Es können nur Standard-Plots zu multiplen Y-Achsen hinzugefÃŒgt werden',0),
    280 25014 => array('Graph::AddText() Du hast versucht, einen leeren Text zum Graph hinzuzufÃŒgen.',0),
    281 25015 => array('Graph::AddLine() Du hast versucht, eine leere Linie zum Graph hinzuzufÃŒgen.',0),
    282 25016 => array('Graph::AddBand() Du hast versucht, ein leeres Band zum Graph hinzuzufÃŒgen.',0),
    283 25017 => array('Du benutzt GD 2.x und versuchst, ein Hintergrundbild in einem Truecolor-Bild zu verwenden. Um Hintergrundbilder mit GD 2.x zu verwenden, ist es notwendig, Truecolor zu aktivieren, indem die USE_TRUECOLOR-Konstante auf TRUE gesetzt wird. Wegen eines Bugs in GD 2.0.1 ist die QualitÀt der Schrift sehr schlecht, wenn Truetype-Schrift in Truecolor-Bildern verwendet werden.',0),
    284 25018 => array('Falscher Dateiname fÃŒr Graph::SetBackgroundImage() : "%s" muss eine gÃŒltige Dateinamenerweiterung (jpg,gif,png) haben, wenn die automatische Dateityperkennung verwenndet werden soll.',1),
    285 25019 => array('Unbekannte Dateinamenerweiterung (%s) in Graph::SetBackgroundImage() fÃŒr Dateiname: "%s"',2),
    286 
    287 25020 => array('Graph::SetScale(): Dar Maximalwert muss größer sein als der Mindestwert.',0),
    288 25021 => array('Unbekannte Achsendefinition fÃŒr die Y-Achse. (%s)',1),
    289 25022 => array('Unbekannte Achsendefinition fÃŒr die X-Achse. (%s)',1),
    290 25023 => array('Nicht unterstÃŒtzter Y2-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1),
    291 25024 => array('Nicht unterstÃŒtzter X-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1),
    292 25025 => array('Nicht unterstÃŒtzte Tick-Dichte: %d',1),
    293 25026 => array('Nicht unterstÃŒtzter Typ der nicht angegebenen Y-Achse. Du hast entweder: 1. einen Y-Achsentyp fÃŒr automatisches Skalieren definiert, aber keine Plots angegeben. 2. eine Achse direkt definiert, aber vergessen, die Tick-Dichte zu festzulegen.',0),
    294 25027 => array('Kann cached CSIM "%s" zum Lesen nicht öffnen.',1),
    295 25028 => array('Apache/PHP hat keine Schreibrechte, in das CSIM-Cache-Verzeichnis (%s) zu schreiben. ÜberprÃŒfe die Rechte.',1),
    296 25029 => array('Kann nicht in das CSIM "%s" schreiben. ÜberprÃŒfe die Schreibrechte und den freien Speicherplatz.',1),
    297 
    298 25030 => array('Fehlender Skriptname fÃŒr StrokeCSIM(). Der Name des aktuellen Skriptes muss als erster Parameter von StrokeCSIM() angegeben werden.',0),
     27325010 => array('Graph::Add() Du hast versucht, einen leeren Plot zum Graph hinzuzufügen.',0),
     27425011 => array('Graph::AddY2() Du hast versucht, einen leeren Plot zum Graph hinzuzufügen.',0),
     27525012 => array('Graph::AddYN() Du hast versucht, einen leeren Plot zum Graph hinzuzufügen.',0),
     27625013 => array('Es können nur Standard-Plots zu multiplen Y-Achsen hinzugefügt werden',0),
     27725014 => array('Graph::AddText() Du hast versucht, einen leeren Text zum Graph hinzuzufügen.',0),
     27825015 => array('Graph::AddLine() Du hast versucht, eine leere Linie zum Graph hinzuzufügen.',0),
     27925016 => array('Graph::AddBand() Du hast versucht, ein leeres Band zum Graph hinzuzufügen.',0),
     28025017 => array('Du benutzt GD 2.x und versuchst, ein Hintergrundbild in einem Truecolor-Bild zu verwenden. Um Hintergrundbilder mit GD 2.x zu verwenden, ist es notwendig, Truecolor zu aktivieren, indem die USE_TRUECOLOR-Konstante auf TRUE gesetzt wird. Wegen eines Bugs in GD 2.0.1 ist die Qualität der Schrift sehr schlecht, wenn Truetype-Schrift in Truecolor-Bildern verwendet werden.',0),
     28125018 => array('Falscher Dateiname für Graph::SetBackgroundImage() : "%s" muss eine gültige Dateinamenerweiterung (jpg,gif,png) haben, wenn die automatische Dateityperkennung verwenndet werden soll.',1),
     28225019 => array('Unbekannte Dateinamenerweiterung (%s) in Graph::SetBackgroundImage() für Dateiname: "%s"',2),
     283
     28425020 => array('Graph::SetScale(): Dar Maximalwert muss größer sein als der Mindestwert.',0),
     28525021 => array('Unbekannte Achsendefinition für die Y-Achse. (%s)',1),
     28625022 => array('Unbekannte Achsendefinition für die X-Achse. (%s)',1),
     28725023 => array('Nicht unterstützter Y2-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1),
     28825024 => array('Nicht unterstützter X-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1),
     28925025 => array('Nicht unterstützte Tick-Dichte: %d',1),
     29025026 => array('Nicht unterstützter Typ der nicht angegebenen Y-Achse. Du hast entweder: 1. einen Y-Achsentyp für automatisches Skalieren definiert, aber keine Plots angegeben. 2. eine Achse direkt definiert, aber vergessen, die Tick-Dichte zu festzulegen.',0),
     29125027 => array('Kann cached CSIM "%s" zum Lesen nicht öffnen.',1),
     29225028 => array('Apache/PHP hat keine Schreibrechte, in das CSIM-Cache-Verzeichnis (%s) zu schreiben. Überprüfe die Rechte.',1),
     29325029 => array('Kann nicht in das CSIM "%s" schreiben. Überprüfe die Schreibrechte und den freien Speicherplatz.',1),
     294
     29525030 => array('Fehlender Skriptname für StrokeCSIM(). Der Name des aktuellen Skriptes muss als erster Parameter von StrokeCSIM() angegeben werden.',0),
    29929625031 => array('Der Achsentyp muss mittels Graph::SetScale() angegeben werden.',0),
    300 25032 => array('Es existieren keine Plots fÃŒr die Y-Achse nbr:%d',1),
     29725032 => array('Es existieren keine Plots für die Y-Achse nbr:%d',1),
    30129825033 => array('',0),
    30229925034 => array('Undefinierte X-Achse kann nicht gezeichnet werden. Es wurden keine Plots definiert.',0),
    303 25035 => array('Du hast Clipping aktiviert. Clipping wird nur fÃŒr Diagramme mit 0 oder 90 Grad Rotation unterstÃŒtzt. Bitte verÀndere Deinen Rotationswinkel (=%d Grad) dementsprechend oder deaktiviere Clipping.',1),
     30025035 => array('Du hast Clipping aktiviert. Clipping wird nur für Diagramme mit 0 oder 90 Grad Rotation unterstützt. Bitte verändere Deinen Rotationswinkel (=%d Grad) dementsprechend oder deaktiviere Clipping.',1),
    30430125036 => array('Unbekannter Achsentyp AxisStyle() : %s',1),
    305 25037 => array('Das Bildformat Deines Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstÃŒtzt. ',1),
     30225037 => array('Das Bildformat Deines Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstützt. ',1),
    30630325038 => array('Das Hintergrundbild scheint von einem anderen Typ (unterschiedliche Dateierweiterung) zu sein als der angegebene Typ. Angegebenen: %s; Datei: %s',2),
    30730425039 => array('Hintergrundbild kann nicht gelesen werden: "%s"',1),
    308305
    309 25040 => array('Es ist nicht möglich, sowohl ein Hintergrundbild als auch eine Hintergrund-Landesflagge anzugeben.',0),
    310 25041 => array('Um Landesflaggen als Hintergrund benutzen zu können, muss die Datei "jpgraph_flags.php" eingefÃŒgt werden (per include).',0),
     30625040 => array('Es ist nicht möglich, sowohl ein Hintergrundbild als auch eine Hintergrund-Landesflagge anzugeben.',0),
     30725041 => array('Um Landesflaggen als Hintergrund benutzen zu können, muss die Datei "jpgraph_flags.php" eingefügt werden (per include).',0),
    31130825042 => array('Unbekanntes Hintergrundbild-Layout',0),
    31230925043 => array('Unbekannter Titelhintergrund-Stil.',0),
    313 25044 => array('Automatisches Skalieren kann nicht verwendet werden, weil es unmöglich ist, einen gÃŒltigen min/max Wert fÃŒr die Y-Achse zu ermitteln (nur Null-Werte).',0),
    314 25045 => array('Die Schriftfamilien FF_HANDWRT und FF_BOOK sind wegen Copyright-Problemen nicht mehr verfÃŒgbar. Diese Schriften können nicht mehr mit JpGraph verteilt werden. Bitte lade Dir Schriften von http://corefonts.sourceforge.net/ herunter.',0),
     31025044 => array('Automatisches Skalieren kann nicht verwendet werden, weil es unmöglich ist, einen gültigen min/max Wert für die Y-Achse zu ermitteln (nur Null-Werte).',0),
     31125045 => array('Die Schriftfamilien FF_HANDWRT und FF_BOOK sind wegen Copyright-Problemen nicht mehr verfügbar. Diese Schriften können nicht mehr mit JpGraph verteilt werden. Bitte lade Dir Schriften von http://corefonts.sourceforge.net/ herunter.',0),
    31531225046 => array('Angegebene TTF-Schriftfamilie (id=%d) ist unbekannt oder existiert nicht. Bitte merke Dir, dass TTF-Schriften wegen Copyright-Problemen nicht mit JpGraph mitgeliefert werden. Du findest MS-TTF-Internetschriften (arial, courier, etc.) zum Herunterladen unter http://corefonts.sourceforge.net/',1),
    316 25047 => array('Stil %s ist nicht verfÃŒgbar fÃŒr Schriftfamilie %s',2),
     31325047 => array('Stil %s ist nicht verfügbar für Schriftfamilie %s',2),
    31731425048 => array('Unbekannte Schriftstildefinition [%s].',1),
    31831525049 => array('Schriftdatei "%s" ist nicht lesbar oder existiert nicht.',1),
    319316
    320 25050 => array('Erstes Argument fÃŒr Text::Text() muss ein String sein.',0),
    321 25051 => array('UngÃŒltige Richtung angegeben fÃŒr Text.',0),
    322 25052 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte vertikale Ausrichtung fÃŒr Text.',0),
    323 25053 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte horizontale Ausrichtung fÃŒr Text.',0),
     31725050 => array('Erstes Argument für Text::Text() muss ein String sein.',0),
     31825051 => array('Ungültige Richtung angegeben für Text.',0),
     31925052 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte vertikale Ausrichtung für Text.',0),
     32025053 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte horizontale Ausrichtung für Text.',0),
    32432125054 => array('Interner Fehler: Unbekannte Grid-Achse %s',1),
    32532225055 => array('Axis::SetTickDirection() sollte nicht mehr verwendet werden. Benutze stattdessen Axis::SetTickSide().',0),
     
    32932625059 => array('SetLabelPos() sollte nicht mehr verwendet werden. Benutze stattdessen Axis::SetLabelSide().',0),
    330327
    331 25060 => array('Unbekannte Ausrichtung angegeben fÃŒr X-Achsentitel (%s).',1),
    332 25061 => array('Unbekannte Ausrichtung angegeben fÃŒr Y-Achsentitel (%s).',1),
    333 25062 => array('Label unter einem Winkel werden fÃŒr die Y-Achse nicht unterstÃŒtzt.',0),
     32825060 => array('Unbekannte Ausrichtung angegeben für X-Achsentitel (%s).',1),
     32925061 => array('Unbekannte Ausrichtung angegeben für Y-Achsentitel (%s).',1),
     33025062 => array('Label unter einem Winkel werden für die Y-Achse nicht unterstützt.',0),
    33433125063 => array('Ticks::SetPrecision() sollte nicht mehr verwendet werden. Benutze stattdessen Ticks::SetLabelFormat() (oder Ticks::SetFormatCallback()).',0),
    335 25064 => array('Kleinere oder größere Schrittgröße ist 0. ÜberprÃŒfe, ob Du fÀlschlicherweise SetTextTicks(0) in Deinem Skript hast. Wenn dies nicht der Fall ist, bist Du eventuell ÃŒber einen Bug in JpGraph gestolpert. Bitte sende einen Report und fÃŒge den Code an, der den Fehler verursacht hat.',0),
    336 25065 => array('Tick-Positionen mÃŒssen als array() angegeben werden',0),
     33225064 => array('Kleinere oder größere Schrittgröße ist 0. Überprüfe, ob Du fälschlicherweise SetTextTicks(0) in Deinem Skript hast. Wenn dies nicht der Fall ist, bist Du eventuell über einen Bug in JpGraph gestolpert. Bitte sende einen Report und füge den Code an, der den Fehler verursacht hat.',0),
     33325065 => array('Tick-Positionen müssen als array() angegeben werden',0),
    33733425066 => array('Wenn die Tick-Positionen und -Label von Hand eingegeben werden, muss die Anzahl der Ticks und der Label gleich sein.',0),
    338 25067 => array('Deine von Hand eingegebene Achse und Ticks sind nicht korrekt. Die Skala scheint zu klein zu sein fÃŒr den Tickabstand.',0),
    339 25068 => array('Ein Plot hat eine ungÃŒltige Achse. Dies kann beispielsweise der Fall sein, wenn Du automatisches Text-Skalieren verwendest, um ein Liniendiagramm zu zeichnen mit nur einem Datenpunkt, oder wenn die BildflÀche zu klein ist. Es kann auch der Fall sein, dass kein Datenpunkt einen numerischen Wert hat (vielleicht nur \'-\' oder \'x\').',0),
    340 25069 => array('Grace muss größer sein als 0',0),
     33525067 => array('Deine von Hand eingegebene Achse und Ticks sind nicht korrekt. Die Skala scheint zu klein zu sein für den Tickabstand.',0),
     33625068 => array('Ein Plot hat eine ungültige Achse. Dies kann beispielsweise der Fall sein, wenn Du automatisches Text-Skalieren verwendest, um ein Liniendiagramm zu zeichnen mit nur einem Datenpunkt, oder wenn die Bildfläche zu klein ist. Es kann auch der Fall sein, dass kein Datenpunkt einen numerischen Wert hat (vielleicht nur \'-\' oder \'x\').',0),
     33725069 => array('Grace muss größer sein als 0',0),
    341338
    34233925070 => array('Deine Daten enthalten nicht-numerische Werte.',0),
    343 25071 => array('Du hast mit SetAutoMin() einen Mindestwert angegeben, der größer ist als der Maximalwert fÃŒr die Achse. Dies ist nicht möglich.',0),
    344 25072 => array('Du hast mit SetAutoMax() einen Maximalwert angegeben, der kleiner ist als der Minimalwert der Achse. Dies ist nicht möglich.',0),
    345 25073 => array('Interner Fehler. Der Integer-Skalierungs-Algorithmus-Vergleich ist außerhalb der Grenzen  (r=%f).',1),
    346 25074 => array('Interner Fehler. Der Skalierungsbereich ist negativ (%f) [fÃŒr %s Achse]. Dieses Problem könnte verursacht werden durch den Versuch, \'ungÃŒltige\' Werte in die Daten-Vektoren einzugeben (z.B. nur String- oder NULL-Werte), was beim automatischen Skalieren einen Fehler erzeugt.',2),
    347 25075 => array('Die automatischen Ticks können nicht gesetzt werden, weil min==max.',0),
    348 25077 => array('Einstellfaktor fÃŒr die Farbe muss größer sein als 0',0),
     34025071 => array('Du hast mit SetAutoMin() einen Mindestwert angegeben, der größer ist als der Maximalwert für die Achse. Dies ist nicht möglich.',0),
     34125072 => array('Du hast mit SetAutoMax() einen Maximalwert angegeben, der kleiner ist als der Minimalwert der Achse. Dies ist nicht möglich.',0),
     34225073 => array('Interner Fehler. Der Integer-Skalierungs-Algorithmus-Vergleich ist außerhalb der Grenzen  (r=%f).',1),
     34325074 => array('Interner Fehler. Der Skalierungsbereich ist negativ (%f) [für %s Achse]. Dieses Problem könnte verursacht werden durch den Versuch, \'ungültige\' Werte in die Daten-Vektoren einzugeben (z.B. nur String- oder NULL-Werte), was beim automatischen Skalieren einen Fehler erzeugt.',2),
     34425075 => array('Die automatischen Ticks können nicht gesetzt werden, weil min==max.',0),
     34525077 => array('Einstellfaktor für die Farbe muss größer sein als 0',0),
    34934625078 => array('Unbekannte Farbe: %s',1),
    350 25079 => array('Unbekannte Farbdefinition: %s, Größe=%d',2),
    351 
    352 25080 => array('Der Alpha-Parameter fÃŒr Farben muss zwischen 0.0 und 1.0 liegen.',0),
    353 25081 => array('Das ausgewÀhlte Grafikformat wird entweder nicht unterstÃŒtzt oder ist unbekannt [%s]',1),
    354 25082 => array('Es wurden ungÃŒltige Größen fÃŒr Breite und Höhe beim Erstellen des Bildes definiert (Breite=%d, Höhe=%d).',2),
    355 25083 => array('Es wurde eine ungÃŒltige Größe beim Kopieren des Bildes angegeben. Die Größe fÃŒr das kopierte Bild wurde auf 1 Pixel oder weniger gesetzt.',0),
    356 25084 => array('Fehler beim Erstellen eines temporÀren GD-Canvas. Möglicherweise liegt ein Arbeitsspeicherproblem vor.',0),
    357 25085 => array('Ein Bild kann nicht aus dem angegebenen String erzeugt werden. Er ist entweder in einem nicht unterstÃŒtzen Format oder er represÀntiert ein kaputtes Bild.',0),
    358 25086 => array('Du scheinst nur GD 1.x installiert zu haben. Um Alphablending zu aktivieren, ist GD 2.x oder höher notwendig. Bitte installiere GD 2.x oder versichere Dich, dass die Konstante USE_GD2 richtig gesetzt ist. StandardmÀßig wird die installierte GD-Version automatisch erkannt. Ganz selten wird GD2 erkannt, obwohl nur GD1 installiert ist. Die Konstante USE_GD2 muss dann zu "false" gesetzt werden.',0),
    359 25087 => array('Diese PHP-Version wurde ohne TTF-UnterstÃŒtzung konfiguriert. PHP muss mit TTF-UnterstÃŒtzung neu kompiliert und installiert werden.',0),
    360 25088 => array('Die GD-SchriftunterstÃŒtzung wurde falsch konfiguriert. Der Aufruf von imagefontwidth() ist fehlerhaft.',0),
    361 25089 => array('Die GD-SchriftunterstÃŒtzung wurde falsch konfiguriert. Der Aufruf von imagefontheight() ist fehlerhaft.',0),
     34725079 => array('Unbekannte Farbdefinition: %s, Größe=%d',2),
     348
     34925080 => array('Der Alpha-Parameter für Farben muss zwischen 0.0 und 1.0 liegen.',0),
     35025081 => array('Das ausgewählte Grafikformat wird entweder nicht unterstützt oder ist unbekannt [%s]',1),
     35125082 => array('Es wurden ungültige Größen für Breite und Höhe beim Erstellen des Bildes definiert (Breite=%d, Höhe=%d).',2),
     35225083 => array('Es wurde eine ungültige Größe beim Kopieren des Bildes angegeben. Die Größe für das kopierte Bild wurde auf 1 Pixel oder weniger gesetzt.',0),
     35325084 => array('Fehler beim Erstellen eines temporären GD-Canvas. Möglicherweise liegt ein Arbeitsspeicherproblem vor.',0),
     35425085 => array('Ein Bild kann nicht aus dem angegebenen String erzeugt werden. Er ist entweder in einem nicht unterstützen Format oder er represäntiert ein kaputtes Bild.',0),
     35525086 => array('Du scheinst nur GD 1.x installiert zu haben. Um Alphablending zu aktivieren, ist GD 2.x oder höher notwendig. Bitte installiere GD 2.x oder versichere Dich, dass die Konstante USE_GD2 richtig gesetzt ist. Standardmäßig wird die installierte GD-Version automatisch erkannt. Ganz selten wird GD2 erkannt, obwohl nur GD1 installiert ist. Die Konstante USE_GD2 muss dann zu "false" gesetzt werden.',0),
     35625087 => array('Diese PHP-Version wurde ohne TTF-Unterstützung konfiguriert. PHP muss mit TTF-Unterstützung neu kompiliert und installiert werden.',0),
     35725088 => array('Die GD-Schriftunterstützung wurde falsch konfiguriert. Der Aufruf von imagefontwidth() ist fehlerhaft.',0),
     35825089 => array('Die GD-Schriftunterstützung wurde falsch konfiguriert. Der Aufruf von imagefontheight() ist fehlerhaft.',0),
    362359
    36336025090 => array('Unbekannte Richtung angegeben im Aufruf von StrokeBoxedText() [%s].',1),
    364 25091 => array('Die interne Schrift untestÃŒtzt das Schreiben von Text in einem beliebigen Winkel nicht. Benutze stattdessen TTF-Schriften.',0),
    365 25092 => array('Es liegt entweder ein Konfigurationsproblem mit TrueType oder ein Problem beim Lesen der Schriftdatei "%s" vor. Versichere Dich, dass die Datei existiert und Leserechte und -pfad vergeben sind. (wenn \'basedir\' restriction in PHP aktiviert ist, muss die Schriftdatei im Dokumentwurzelverzeichnis abgelegt werden). Möglicherweise ist die FreeType-Bibliothek falsch installiert. Versuche, mindestens zur FreeType-Version 2.1.13 zu aktualisieren und kompiliere GD mit einem korrekten Setup neu, damit die FreeType-Bibliothek gefunden werden kann.',1),
     36125091 => array('Die interne Schrift untestützt das Schreiben von Text in einem beliebigen Winkel nicht. Benutze stattdessen TTF-Schriften.',0),
     36225092 => array('Es liegt entweder ein Konfigurationsproblem mit TrueType oder ein Problem beim Lesen der Schriftdatei "%s" vor. Versichere Dich, dass die Datei existiert und Leserechte und -pfad vergeben sind. (wenn \'basedir\' restriction in PHP aktiviert ist, muss die Schriftdatei im Dokumentwurzelverzeichnis abgelegt werden). Möglicherweise ist die FreeType-Bibliothek falsch installiert. Versuche, mindestens zur FreeType-Version 2.1.13 zu aktualisieren und kompiliere GD mit einem korrekten Setup neu, damit die FreeType-Bibliothek gefunden werden kann.',1),
    36636325093 => array('Die Schriftdatei "%s" kann nicht gelesen werden beim Aufruf von Image::GetBBoxTTF. Bitte versichere Dich, dass die Schrift gesetzt wurde, bevor diese Methode aufgerufen wird, und dass die Schrift im TTF-Verzeichnis installiert ist.',1),
    36736425094 => array('Die Textrichtung muss in einem Winkel zwischen 0 und 90 engegeben werden.',0),
    36836525095 => array('Unbekannte Schriftfamilien-Definition. ',0),
    369 25096 => array('Der Farbpalette können keine weiteren Farben zugewiesen werden. Dem Bild wurde bereits die größtmögliche Anzahl von Farben (%d) zugewiesen und die Palette ist voll. Verwende stattdessen ein TrueColor-Bild',0),
     36625096 => array('Der Farbpalette können keine weiteren Farben zugewiesen werden. Dem Bild wurde bereits die größtmögliche Anzahl von Farben (%d) zugewiesen und die Palette ist voll. Verwende stattdessen ein TrueColor-Bild',0),
    37036725097 => array('Eine Farbe wurde als leerer String im Aufruf von PushColor() angegegeben.',0),
    37136825098 => array('Negativer Farbindex. Unpassender Aufruf von PopColor().',0),
    372 25099 => array('Die Parameter fÃŒr Helligkeit und Kontrast sind außerhalb des zulÀssigen Bereichs [-1,1]',0),
     36925099 => array('Die Parameter für Helligkeit und Kontrast sind außerhalb des zulässigen Bereichs [-1,1]',0),
    373370
    37437125100 => array('Es liegt ein Problem mit der Farbpalette und dem GD-Setup vor. Bitte deaktiviere anti-aliasing oder verwende GD2 mit TrueColor. Wenn die GD2-Bibliothek installiert ist, versichere Dich, dass die Konstante USE_GD2 auf "true" gesetzt und TrueColor aktiviert ist.',0),
    375 25101 => array('UngÃŒltiges numerisches Argument fÃŒr SetLineStyle(): (%d)',1),
    376 25102 => array('UngÃŒltiges String-Argument fÃŒr SetLineStyle(): %s',1),
    377 25103 => array('UngÃŒltiges Argument fÃŒr SetLineStyle %s',1),
     37225101 => array('Ungültiges numerisches Argument für SetLineStyle(): (%d)',1),
     37325102 => array('Ungültiges String-Argument für SetLineStyle(): %s',1),
     37425103 => array('Ungültiges Argument für SetLineStyle %s',1),
    37837525104 => array('Unbekannter Linientyp: %s',1),
    379 25105 => array('Es wurden NULL-Daten fÃŒr ein gefÃŒlltes Polygon angegeben. Sorge dafÃŒr, dass keine NULL-Daten angegeben werden.',0),
    380 25106 => array('Image::FillToBorder : es können keine weiteren Farben zugewiesen werden.',0),
    381 25107 => array('In Datei "%s" kann nicht geschrieben werden. ÜberprÃŒfe die aktuellen Schreibrechte.',1),
    382 25108 => array('Das Bild kann nicht gestreamt werden. Möglicherweise liegt ein Fehler im PHP/GD-Setup vor. Kompiliere PHP neu und verwende die eingebaute GD-Bibliothek, die mit PHP angeboten wird.',0),
    383 25109 => array('Deine PHP- (und GD-lib-) Installation scheint keine bekannten Grafikformate zu unterstÃŒtzen. Sorge zunÀchst dafÃŒr, dass GD als PHP-Modul kompiliert ist. Wenn Du außerdem JPEG-Bilder verwenden willst, musst Du die JPEG-Bibliothek installieren. Weitere Details sind in der PHP-Dokumentation zu finden.',0),
    384 
    385 25110 => array('Dein PHP-Installation unterstÃŒtzt das gewÀhlte Grafikformat nicht: %s',1),
    386 25111 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1),
     37625105 => array('Es wurden NULL-Daten für ein gefülltes Polygon angegeben. Sorge dafür, dass keine NULL-Daten angegeben werden.',0),
     37725106 => array('Image::FillToBorder : es können keine weiteren Farben zugewiesen werden.',0),
     37825107 => array('In Datei "%s" kann nicht geschrieben werden. Überprüfe die aktuellen Schreibrechte.',1),
     37925108 => array('Das Bild kann nicht gestreamt werden. Möglicherweise liegt ein Fehler im PHP/GD-Setup vor. Kompiliere PHP neu und verwende die eingebaute GD-Bibliothek, die mit PHP angeboten wird.',0),
     38025109 => array('Deine PHP- (und GD-lib-) Installation scheint keine bekannten Grafikformate zu unterstützen. Sorge zunächst dafür, dass GD als PHP-Modul kompiliert ist. Wenn Du außerdem JPEG-Bilder verwenden willst, musst Du die JPEG-Bibliothek installieren. Weitere Details sind in der PHP-Dokumentation zu finden.',0),
     381
     38225110 => array('Dein PHP-Installation unterstützt das gewählte Grafikformat nicht: %s',1),
     38325111 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1),
    38738425112 => array('Das Datum der gecacheten Datei (%s) liegt in der Zukunft.',1),
    388 25113 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1),
    389 25114 => array('PHP hat nicht die erforderlichen Rechte, um in die Cache-Datei %s zu schreiben. Bitte versichere Dich, dass der Benutzer, der PHP anwendet, die entsprechenden Schreibrechte fÃŒr die Datei hat, wenn Du das Cache-System in JPGraph verwenden willst.',1),
    390 25115 => array('Berechtigung fÃŒr gecachetes Bild %s kann nicht gesetzt werden. Problem mit den Rechten?',1),
    391 25116 => array('Datei kann nicht aus dem Cache %s geöffnet werden',1),
    392 25117 => array('Gecachetes Bild %s kann nicht zum Lesen geöffnet werden.',1),
     38525113 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1),
     38625114 => array('PHP hat nicht die erforderlichen Rechte, um in die Cache-Datei %s zu schreiben. Bitte versichere Dich, dass der Benutzer, der PHP anwendet, die entsprechenden Schreibrechte für die Datei hat, wenn Du das Cache-System in JPGraph verwenden willst.',1),
     38725115 => array('Berechtigung für gecachetes Bild %s kann nicht gesetzt werden. Problem mit den Rechten?',1),
     38825116 => array('Datei kann nicht aus dem Cache %s geöffnet werden',1),
     38925117 => array('Gecachetes Bild %s kann nicht zum Lesen geöffnet werden.',1),
    39339025118 => array('Verzeichnis %s kann nicht angelegt werden. Versichere Dich, dass PHP die Schreibrechte in diesem Verzeichnis hat.',1),
    394 25119 => array('Rechte fÃŒr Datei %s können nicht gesetzt werden. Problem mit den Rechten?',1),
    395 
    396 25120 => array('Die Position fÃŒr die Legende muss als Prozentwert im Bereich 0-1 angegeben werden.',0),
    397 25121 => array('Eine leerer Datenvektor wurde fÃŒr den Plot eingegeben. Es muss wenigstens ein Datenpunkt vorliegen.',0),
     39125119 => array('Rechte für Datei %s können nicht gesetzt werden. Problem mit den Rechten?',1),
     392
     39325120 => array('Die Position für die Legende muss als Prozentwert im Bereich 0-1 angegeben werden.',0),
     39425121 => array('Eine leerer Datenvektor wurde für den Plot eingegeben. Es muss wenigstens ein Datenpunkt vorliegen.',0),
    39839525122 => array('Stroke() muss als Subklasse der Klasse Plot definiert sein.',0),
    39939625123 => array('Du kannst keine Text-X-Achse mit X-Koordinaten verwenden. Benutze stattdessen eine "int" oder "lin" Achse.',0),
    400 25124 => array('Der Eingabedatenvektor mus aufeinanderfolgende Werte von 0 aufwÀrts beinhalten. Der angegebene Y-Vektor beginnt mit leeren Werten (NULL).',0),
    401 25125 => array('UngÃŒltige Richtung fÃŒr statische Linie.',0),
    402 25126 => array('Es kann kein TrueColor-Bild erzeugt werden. ÜberprÃŒfe, ob die GD2-Bibliothek und PHP korrekt aufgesetzt wurden.',0),
     39725124 => array('Der Eingabedatenvektor mus aufeinanderfolgende Werte von 0 aufwärts beinhalten. Der angegebene Y-Vektor beginnt mit leeren Werten (NULL).',0),
     39825125 => array('Ungültige Richtung für statische Linie.',0),
     39925126 => array('Es kann kein TrueColor-Bild erzeugt werden. Überprüfe, ob die GD2-Bibliothek und PHP korrekt aufgesetzt wurden.',0),
    40340025127 => array('The library has been configured for automatic encoding conversion of Japanese fonts. This requires that PHP has the mb_convert_encoding() function. Your PHP installation lacks this function (PHP needs the "--enable-mbstring" when compiled).',0),
    40440125128 => array('The function imageantialias() is not available in your PHP installation. Use the GD version that comes with PHP and not the standalone version.',0),
    40540225129 => array('Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.',0),
    406 25130 => array('Too small plot area. (%d x %d). With the given image size and margins there is to little space left for the plot. Increase the plot size or reduce the margins.',2),
    407 
    408 25131 => array('StrokeBoxedText2() only supports TTF fonts and not built-in bitmap fonts.',0),
    409 25132 => array('Undefined property %s.',1), // @todo translate
    410 25133 => array('Use Graph::SetTheme() after Graph::SetScale().',0), // @todo translate
    411 
    412 /*
    413 **  jpgraph_led
    414 */
    415 
    416 25500 => array('Multibyte strings must be enabled in the PHP installation in order to run the LED module so that the function mb_strlen() is available. See PHP documentation for more information.',0),
    417 
    418 
    419403/*
    420404**---------------------------------------------------------------------------------------------
     
    427411*/
    428412
    429 27001 => array('GTextTable: UngÃŒltiges Argument fÃŒr Set(). Das Array-Argument muss 2-- dimensional sein.',0),
    430 27002 => array('GTextTable: UngÃŒltiges Argument fÃŒr Set()',0),
    431 27003 => array('GTextTable: Falsche Anzahl von Argumenten fÃŒr GTextTable::SetColor()',0),
    432 27004 => array('GTextTable: Angegebener Zellenbereich, der verschmolzen werden soll, ist ungÃŒltig.',0),
    433 27005 => array('GTextTable: Bereits verschmolzene Zellen im Bereich (%d,%d) bis (%d,%d) können nicht ein weiteres Mal verschmolzen werden.',4),
    434 27006 => array('GTextTable: Spalten-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1),
    435 27007 => array('GTextTable: Zeilen-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1),
    436 27008 => array('GTextTable: Spalten- und Zeilengröße mÃŒssen zu den Dimensionen der Tabelle passen.',0),
     41327001 => array('GTextTable: Ungültiges Argument für Set(). Das Array-Argument muss 2-- dimensional sein.',0),
     41427002 => array('GTextTable: Ungültiges Argument für Set()',0),
     41527003 => array('GTextTable: Falsche Anzahl von Argumenten für GTextTable::SetColor()',0),
     41627004 => array('GTextTable: Angegebener Zellenbereich, der verschmolzen werden soll, ist ungültig.',0),
     41727005 => array('GTextTable: Bereits verschmolzene Zellen im Bereich (%d,%d) bis (%d,%d) können nicht ein weiteres Mal verschmolzen werden.',4),
     41827006 => array('GTextTable: Spalten-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1),
     41927007 => array('GTextTable: Zeilen-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1),
     42027008 => array('GTextTable: Spalten- und Zeilengröße müssen zu den Dimensionen der Tabelle passen.',0),
    43742127009 => array('GTextTable: Die Anzahl der Tabellenspalten oder -zeilen ist 0. Versichere Dich, dass die Methoden Init() oder Set() aufgerufen werden.',0),
    43842227010 => array('GTextTable: Es wurde keine Ausrichtung beim Aufruf von SetAlign() angegeben.',0),
    43942327011 => array('GTextTable: Es wurde eine unbekannte Ausrichtung beim Aufruf von SetAlign() abgegeben. Horizontal=%s, Vertikal=%s',2),
    440 27012 => array('GTextTable: Interner Fehler. Es wurde ein ungÃŒltiges Argument festgeleget %s',1),
    441 27013 => array('GTextTable: Das Argument fÃŒr FormatNumber() muss ein String sein.',0),
     42427012 => array('GTextTable: Interner Fehler. Es wurde ein ungültiges Argument festgeleget %s',1),
     42527013 => array('GTextTable: Das Argument für FormatNumber() muss ein String sein.',0),
    44242627014 => array('GTextTable: Die Tabelle wurde weder mit einem Aufruf von Set() noch von Init() initialisiert.',0),
    44342727015 => array('GTextTable: Der Zellenbildbedingungstyp muss entweder TIMG_WIDTH oder TIMG_HEIGHT sein.',0),
     
    447431*/
    448432
    449 22001 => array('Die Gesamtsumme der prozentualen Anteile aller Windrosenarme darf 100%% nicht ÃŒberschreiten!\n(Aktuell max: %d)',1),
    450 22002 => array('Das Bild ist zu klein fÃŒr eine Skala. Bitte vergrößere das Bild.',0),
    451 22004 => array('Die Etikettendefinition fÃŒr Windrosenrichtungen mÃŒssen 16 Werte haben (eine fÃŒr jede Kompassrichtung).',0),
    452 22005 => array('Der Linientyp fÃŒr radiale Linien muss einer von ("solid","dotted","dashed","longdashed") sein.',0),
    453 22006 => array('Es wurde ein ungÃŒltiger Windrosentyp angegeben.',0),
    454 22007 => array('Es wurden zu wenig Werte fÃŒr die Bereichslegende angegeben.',0),
     43322001 => array('Die Gesamtsumme der prozentualen Anteile aller Windrosenarme darf 100%% nicht überschreiten!\n(Aktuell max: %d)',1),
     43422002 => array('Das Bild ist zu klein für eine Skala. Bitte vergrößere das Bild.',0),
     43522004 => array('Die Etikettendefinition für Windrosenrichtungen müssen 16 Werte haben (eine für jede Kompassrichtung).',0),
     43622005 => array('Der Linientyp für radiale Linien muss einer von ("solid","dotted","dashed","longdashed") sein.',0),
     43722006 => array('Es wurde ein ungültiger Windrosentyp angegeben.',0),
     43822007 => array('Es wurden zu wenig Werte für die Bereichslegende angegeben.',0),
    45543922008 => array('Interner Fehler: Versuch, eine freie Windrose zu plotten, obwohl der Typ keine freie Windrose ist.',0),
    45644022009 => array('Du hast die gleiche Richtung zweimal angegeben, einmal mit einem Winkel und einmal mit einer Kompassrichtung (%f Grad).',0),
    45744122010 => array('Die Richtung muss entweder ein numerischer Wert sein oder eine der 16 Kompassrichtungen',0),
    45844222011 => array('Der Windrosenindex muss ein numerischer oder Richtungswert sein. Du hast angegeben Index=%d',1),
    459 22012 => array('Die radiale Achsendefinition fÃŒr die Windrose enthÀlt eine nicht aktivierte Richtung.',0),
    460 22013 => array('Du hast dasselbe Look&Feel fÃŒr die gleiche Kompassrichtung zweimal engegeben, einmal mit Text und einmal mit einem Index (Index=%d)',1),
    461 22014 => array('Der Index fÃŒr eine Kompassrichtung muss zwischen 0 und 15 sein.',0),
     44322012 => array('Die radiale Achsendefinition für die Windrose enthält eine nicht aktivierte Richtung.',0),
     44422013 => array('Du hast dasselbe Look&Feel für die gleiche Kompassrichtung zweimal engegeben, einmal mit Text und einmal mit einem Index (Index=%d)',1),
     44522014 => array('Der Index für eine Kompassrichtung muss zwischen 0 und 15 sein.',0),
    46244622015 => array('Du hast einen unbekannten Windrosenplottyp angegeben.',0),
    46344722016 => array('Der Windrosenarmindex muss ein numerischer oder ein Richtungswert sein.',0),
    46444822017 => array('Die Windrosendaten enthalten eine Richtung, die nicht aktiviert ist. Bitte berichtige, welche Label angezeigt werden sollen.',0),
    465 22018 => array('Du hast fÃŒr dieselbe Kompassrichtung zweimal Daten angegeben, einmal mit Text und einmal mit einem Index (Index=%d)',1),
    466 22019 => array('Der Index fÃŒr eine Richtung muss zwischen 0 und 15 sein. Winkel dÃŒrfen nicht fÃŒr einen regelmÀßigen Windplot angegeben werden, sondern entweder ein Index oder eine Kompassrichtung.',0),
    467 22020 => array('Der Windrosenplot ist zu groß fÃŒr die angegebene Bildgröße. Benutze entweder WindrosePlot::SetSize(), um den Plot kleiner zu machen oder vergrößere das Bild im ursprÃŒnglichen Aufruf von WindroseGraph().',0),
     44922018 => array('Du hast für dieselbe Kompassrichtung zweimal Daten angegeben, einmal mit Text und einmal mit einem Index (Index=%d)',1),
     45022019 => array('Der Index für eine Richtung muss zwischen 0 und 15 sein. Winkel dürfen nicht für einen regelmäßigen Windplot angegeben werden, sondern entweder ein Index oder eine Kompassrichtung.',0),
     45122020 => array('Der Windrosenplot ist zu groß für die angegebene Bildgröße. Benutze entweder WindrosePlot::SetSize(), um den Plot kleiner zu machen oder vergrößere das Bild im ursprünglichen Aufruf von WindroseGraph().',0),
    46845222021 => array('It is only possible to add Text, IconPlot or WindrosePlot to a Windrose Graph',0),
    469453
     
    473457
    47445813001 => array('Unbekannter Nadeltypstil (%d).',1),
    475 13002 => array('Ein Wert fÃŒr das Odometer (%f) ist außerhalb des angegebenen Bereichs [%f,%f]',3),
     45913002 => array('Ein Wert für das Odometer (%f) ist außerhalb des angegebenen Bereichs [%f,%f]',3),
    476460
    477461/*
     
    4814651001 => array('Unbekannte Kodier-Specifikation: %s',1),
    4824661002 => array('datenvalidierung schlug fehl. [%s] kann nicht mittels der Kodierung "%s" kodiert werden',2),
    483 1003 => array('Interner Kodierfehler. Kodieren von %s ist nicht möglich in Code 128',1),
     4671003 => array('Interner Kodierfehler. Kodieren von %s ist nicht möglich in Code 128',1),
    4844681004 => array('Interner barcode Fehler. Unbekannter UPC-E Kodiertyp: %s',1),
    4854691005 => array('Interner Fehler. Das Textzeichen-Tupel (%s, %s) kann nicht im Code-128 Zeichensatz C kodiert werden.',2),
    486 1006 => array('Interner Kodierfehler fÃŒr CODE 128. Es wurde versucht, CTRL in CHARSET != A zu kodieren.',0),
    487 1007 => array('Interner Kodierfehler fÃŒr CODE 128. Es wurde versucht, DEL in CHARSET != B zu kodieren.',0),
    488 1008 => array('Interner Kodierfehler fÃŒr CODE 128. Es wurde versucht, kleine Buchstaben in CHARSET != B zu kodieren.',0),
    489 1009 => array('Kodieren mittels CODE 93 wird noch nicht unterstÃŒtzt.',0),
    490 1010 => array('Kodieren mittels POSTNET wird noch nicht unterstÃŒtzt.',0),
    491 1011 => array('Nicht untrstÃŒtztes Barcode-Backend fÃŒr den Typ %s',1),
     4701006 => array('Interner Kodierfehler für CODE 128. Es wurde versucht, CTRL in CHARSET != A zu kodieren.',0),
     4711007 => array('Interner Kodierfehler für CODE 128. Es wurde versucht, DEL in CHARSET != B zu kodieren.',0),
     4721008 => array('Interner Kodierfehler für CODE 128. Es wurde versucht, kleine Buchstaben in CHARSET != B zu kodieren.',0),
     4731009 => array('Kodieren mittels CODE 93 wird noch nicht unterstützt.',0),
     4741010 => array('Kodieren mittels POSTNET wird noch nicht unterstützt.',0),
     4751011 => array('Nicht untrstütztes Barcode-Backend für den Typ %s',1),
    492476
    493477/*
     
    495479*/
    496480
    497 26000 => array('PDF417: The PDF417 module requires that the PHP installation must support the function bcmod(). This is normally enabled at compile time. See documentation for more information.',0),
    49848126001 => array('PDF417: Die Anzahl der Spalten muss zwischen 1 und 30 sein.',0),
    49948226002 => array('PDF417: Der Fehler-Level muss zwischen 0 und 8 sein.',0),
    500 26003 => array('PDF417: UngÃŒltiges Format fÃŒr Eingabedaten, um sie mit PDF417 zu kodieren.',0),
    501 26004 => array('PDF417: die eigebenen Daten können nicht mit Fehler-Level %d und %d spalten kodiert werden, weil daraus zu viele Symbole oder mehr als 90 Zeilen resultieren.',2),
    502 26005 => array('PDF417: Die Datei "%s" kann nicht zum Schreiben geöffnet werden.',1),
    503 26006 => array('PDF417: Interner Fehler. Die Eingabedatendatei fÃŒr PDF417-Cluster %d ist fehlerhaft.',1),
    504 26007 => array('PDF417: Interner Fehler. GetPattern: UngÃŒltiger Code-Wert %d (Zeile %d)',2),
     48326003 => array('PDF417: Ungültiges Format für Eingabedaten, um sie mit PDF417 zu kodieren.',0),
     48426004 => array('PDF417: die eigebenen Daten können nicht mit Fehler-Level %d und %d spalten kodiert werden, weil daraus zu viele Symbole oder mehr als 90 Zeilen resultieren.',2),
     48526005 => array('PDF417: Die Datei "%s" kann nicht zum Schreiben geöffnet werden.',1),
     48626006 => array('PDF417: Interner Fehler. Die Eingabedatendatei für PDF417-Cluster %d ist fehlerhaft.',1),
     48726007 => array('PDF417: Interner Fehler. GetPattern: Ungültiger Code-Wert %d (Zeile %d)',2),
    50548826008 => array('PDF417: Interner Fehler. Modus wurde nicht in der Modusliste!! Modus %d',1),
    506 26009 => array('PDF417: Kodierfehler: UngÃŒltiges Zeichen. Zeichen kann nicht mit ASCII-Code %d kodiert werden.',1),
     48926009 => array('PDF417: Kodierfehler: Ungültiges Zeichen. Zeichen kann nicht mit ASCII-Code %d kodiert werden.',1),
    50749026010 => array('PDF417: Interner Fehler: Keine Eingabedaten beim Dekodieren.',0),
    508 26011 => array('PDF417: Kodierfehler. Numerisches Kodieren bei nicht-numerischen Daten nicht möglich.',0),
    509 26012 => array('PDF417: Interner Fehler. Es wurden fÃŒr den Binary-Kompressor keine Daten zum Dekodieren eingegeben.',0),
     49126011 => array('PDF417: Kodierfehler. Numerisches Kodieren bei nicht-numerischen Daten nicht möglich.',0),
     49226012 => array('PDF417: Interner Fehler. Es wurden für den Binary-Kompressor keine Daten zum Dekodieren eingegeben.',0),
    51049326013 => array('PDF417: Interner Fehler. Checksum Fehler. Koeffiziententabellen sind fehlerhaft.',0),
    511 26014 => array('PDF417: Interner Fehler. Es wurden keine Daten zum Berechnen von Kodewörtern eingegeben.',0),
    512 26015 => array('PDF417: Interner Fehler. Ein Eintrag 0 in die StatusÃŒbertragungstabellen ist nicht NULL. Eintrag 1 = (%s)',1),
    513 26016 => array('PDF417: Interner Fehler: Nichtregistrierter StatusÃŒbertragungsmodus beim Dekodieren.',0),
    514 
    515 
    516 /*
    517 ** jpgraph_contour
    518 */
    519 
    520 28001 => array('Dritten parameter fur Contour muss ein vector der fargen sind.',0),
    521 28002 => array('Die anzahlen der farges jeder isobar linien muss gleich sein.',0),
    522 28003 => array('ContourPlot Interner Fehler: isobarHCrossing: Spalten index ist zu hoch (%d)',1),
    523 28004 => array('ContourPlot Interner Fehler: isobarHCrossing: Reihe index ist zu hoch (%d)',1),
    524 28005 => array('ContourPlot Interner Fehler: isobarVCrossing: Reihe index ist zu hoch (%d)',1),
    525 28006 => array('ContourPlot Interner Fehler: isobarVCrossing: Spalten index ist zu hoch (%d)',1),
    526 28007 => array('ContourPlot. Interpolation faktor ist zu hoch (>5)',0),
    527 
    528 
    529 /*
    530  * jpgraph_matrix and colormap
    531 */
    532 29201 => array('Min range value must be less or equal to max range value for colormaps',0),
    533 29202 => array('The distance between min and max value is too small for numerical precision',0),
    534 29203 => array('Number of color quantification level must be at least %d',1),
    535 29204 => array('Number of colors (%d) is invalid for this colormap. It must be a number that can be written as: %d + k*%d',3),
    536 29205 => array('Colormap specification out of range. Must be an integer in range [0,%d]',1),
    537 29206 => array('Invalid object added to MatrixGraph',0),
    538 29207 => array('Empty input data specified for MatrixPlot',0),
    539 29208 => array('Unknown side specifiction for matrix labels "%s"',1),
    540 29209 => array('CSIM Target matrix must be the same size as the data matrix (csim=%d x %d, data=%d x %d)',4),
    541 29210 => array('CSIM Target for matrix labels does not match the number of labels (csim=%d, labels=%d)',2),
    542 
    543 
    544 /*
    545 * jpgraph_theme
    546 */
    547 30001 => array("Theme::%s() is not defined. \nPlease make %s(\$graph) function in your theme classs.",2),
     49426014 => array('PDF417: Interner Fehler. Es wurden keine Daten zum Berechnen von Kodewörtern eingegeben.',0),
     49526015 => array('PDF417: Interner Fehler. Ein Eintrag 0 in die Statusübertragungstabellen ist nicht NULL. Eintrag 1 = (%s)',1),
     49626016 => array('PDF417: Interner Fehler: Nichtregistrierter Statusübertragungsmodus beim Dekodieren.',0),
    548497
    549498
  • trunk/client/modules/Elezioni/grafici/lang/en.inc.php

    r265 r267  
    11<?php
    22/*=======================================================================
    3 // File:     EN.INC.PHP
     3// File:        EN.INC.PHP
    44// Description: English language file for error messages
    5 // Created:     2006-01-25
    6 // Ver:        $Id: en.inc.php 1886 2009-10-01 23:30:16Z ljp $
     5// Created:     2006-01-25
     6// Ver:         $Id: en.inc.php 1017 2008-07-08 06:09:28Z ljp $
    77//
    8 // Copyright (c) Asial Corporation. All rights reserved.
     8// Copyright (c) Aditus Consulting. All rights reserved.
    99//========================================================================
    1010*/
     
    1616** Headers already sent error. This is formatted as HTML different since this will be sent back directly as text
    1717*/
    18 10  => array('<table border="1"><tr><td style="color:darkred; font-size:1.2em;"><b>JpGraph Error:</b>
     1810  => array('<table border="1"><tr><td style="color:darkred; font-size:1.2em;"><b>JpGraph Error:</b> 
    1919HTTP headers have already been sent.<br>Caused by output from file <b>%s</b> at line <b>%d</b>.</td></tr><tr><td><b>Explanation:</b><br>HTTP headers have already been sent back to the browser indicating the data as text before the library got a chance to send it\'s image HTTP header to this browser. This makes it impossible for the library to send back image data to the browser (since that would be interpretated as text by the browser and show up as junk text).<p>Most likely you have some text in your script before the call to <i>Graph::Stroke()</i>. If this texts gets sent back to the browser the browser will assume that all data is plain text. Look for any text, even spaces and newlines, that might have been sent back to the browser. <p>For example it is a common mistake to leave a blank line before the opening "<b>&lt;?php</b>".</td></tr></table>',2),
    2020
     
    76766001 => array('Internal error. Height for ActivityTitles is < 0',0),
    77776002 => array('You can\'t specify negative sizes for Gantt graph dimensions. Use 0 to indicate that you want the library to automatically determine a dimension.',0),
    78 6003 => array('Invalid format for Constrain parameter at index=%d in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Constrain-To,Constrain-Type)',1),
    79 6004 => array('Invalid format for Progress parameter at index=%d in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Progress)',1),
     786003 => array('Invalid format for Constrain parameter at index=%d in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Constrain-To,Constrain-Type)',1), 
     796004 => array('Invalid format for Progress parameter at index=%d in CreateSimple(). Parameter must start with index 0 and contain arrays of (Row,Progress)',1), 
    80806005 => array('SetScale() is not meaningful with Gantt charts.',0),
    81816006 => array('Cannot autoscale Gantt chart. No dated activities exist. [GetBarMinMax() start >= n]',0),
     
    1031036031 => array('Unknown arrow type for link.',0),
    1041046032 => array('Internal error: Unknown path type (=%d) specified for link.',1),
    105 6033 => array('Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)',0),
    106105
    107106/*
     
    18818715010 => array('Sum of all data is 0 for Pie.',0),
    18918815011 => array('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.',0),
    190 15012 => array('PiePlot::SetTheme() is no longer supported. Use PieGraph::SetTheme()',0),
    191189
    192190/*
     
    25925724002 => array('FuncGenerator : Syntax error in function specification ',0),
    26025824003 => array('DateScaleUtils: Unknown tick type specified in call to GetTicks()',0),
    261 24004 => array('ReadCSV2: Column count mismatch in %s line %d',2),
    262259/*
    263260**  jpgraph
     
    275272
    27627325010 => array('Graph::Add() You tried to add a null plot to the graph.',0),
    277 25011 => array('Graph::AddY2() You tried to add a null plot to the graph.',0),
    278 25012 => array('Graph::AddYN() You tried to add a null plot to the graph.',0),
     27425011 => array('Graph::AddY2() You tried to add a null plot to the graph.',0), 
     27525012 => array('Graph::AddYN() You tried to add a null plot to the graph.',0), 
    27927625013 => array('You can only add standard plots to multiple Y-axis',0),
    280 25014 => array('Graph::AddText() You tried to add a null text to the graph.',0),
    281 25015 => array('Graph::AddLine() You tried to add a null line to the graph.',0),
     27725014 => array('Graph::AddText() You tried to add a null text to the graph.',0), 
     27825015 => array('Graph::AddLine() You tried to add a null line to the graph.',0), 
    28227925016 => array('Graph::AddBand() You tried to add a null band to the graph.',0),
    28328025017 => array('You are using GD 2.x and are trying to use a background images on a non truecolor image. To use background images with GD 2.x it is necessary to enable truecolor by setting the USE_TRUECOLOR constant to TRUE. Due to a bug in GD 2.0.1 using any truetype fonts with truecolor images will result in very poor quality fonts.',0),
     
    30530225037 => array('The image format of your background image (%s) is not supported in your system configuration. ',1),
    30630325038 => array('Background image seems to be of different type (has different file extension) than specified imagetype. Specified: %s File: %s',2),
    307 25039 => array('Can\'t read background image: "%s"',1),
     30425039 => array('Can\'t read background image: "%s"',1), 
    308305
    30930625040 => array('It is not possible to specify both a background image and a background country flag.',0),
     
    32532225055 => array('Axis::SetTickDirection() is deprecated. Use Axis::SetTickSide() instead',0),
    32632325056 => array('SetTickLabelMargin() is deprecated. Use Axis::SetLabelMargin() instead.',0),
    327 25057 => array('SetTextTicks() is deprecated. Use SetTextTickInterval() instead.',0),
     32425057 => array('SetTextTicks() is deprecated. Use SetTextTickInterval() instead.',0), 
    32832525058 => array('Text label interval must be specified >= 1.',0),
    32932625059 => array('SetLabelPos() is deprecated. Use Axis::SetLabelSide() instead.',0),
     
    36936625097 => array('Color specified as empty string in PushColor().',0),
    37036725098 => array('Negative Color stack index. Unmatched call to PopColor()',0),
    371 25099 => array('Parameters for brightness and Contrast out of range [-1,1]',0),
     36825099 => array('Parameters for brightness and Contrast out of range [-1,1]',0), 
    372369
    37337025100 => array('Problem with color palette and your GD setup. Please disable anti-aliasing or use GD2 with true-color. If you have GD2 library installed please make sure that you have set the USE_GD2 constant to true and truecolor is enabled.',0),
     
    38838525114 => array('PHP has not enough permissions to write to the cache file "%s". Please make sure that the user running PHP has write permission for this file if you wan to use the cache system with JpGraph.',1),
    38938625115 => array('Can\'t set permission for cached image "%s". Permission problem?',1),
    390 25116 => array('Cant open file from cache "%s"',1),
     38725116 => array('Cant open file from cache "%s"',1), 
    39138825117 => array('Can\'t open cached image "%s" for reading.',1),
    39238925118 => array('Can\'t create directory "%s". Make sure PHP has write permission to this directory.',1),
     
    40340025128 => array('The function imageantialias() is not available in your PHP installation. Use the GD version that comes with PHP and not the standalone version.',0),
    40440125129 => array('Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.',0),
    405 25130 => array('Too small plot area. (%d x %d). With the given image size and margins there is to little space left for the plot. Increase the plot size or reduce the margins.',2),
    406 
    407 25131 => array('StrokeBoxedText2() only supports TTF fonts and not built-in bitmap fonts.',0),
    408 25132 => array('Undefined property %s.',1),
    409 25133 => array('Use Graph::SetTheme() after Graph::SetScale().',0),
    410 
    411 /*
    412 **  jpgraph_led
    413 */
    414 
    415 25500 => array('Multibyte strings must be enabled in the PHP installation in order to run the LED module so that the function mb_strlen() is available. See PHP documentation for more information.',0),
     402
    416403
    417404/*
     
    422409
    423410/*
    424 **  jpgraph_table
     411**  jpgraph_table 
    425412*/
    426413
     
    491478** PDF417
    492479*/
    493 26000 => array('PDF417: The PDF417 module requires that the PHP installation must support the function bcmod(). This is normally enabled at compile time. See documentation for more information.',0),
     480
    49448126001 => array('PDF417: Number of Columns must be >= 1 and <= 30',0),
    49548226002 => array('PDF417: Error level must be between 0 and 8',0),
     
    50949626016 => array('PDF417: Internal error: Unrecognized state transition mode in decode.',0),
    510497
    511 /*
    512 ** jpgraph_contour
    513 */
    514 
    515 28001 => array('Third argument to Contour must be an array of colors.',0),
    516 28002 => array('Number of colors must equal the number of isobar lines specified',0),
    517 28003 => array('ContourPlot Internal Error: isobarHCrossing: Coloumn index too large (%d)',1),
    518 28004 => array('ContourPlot Internal Error: isobarHCrossing: Row index too large (%d)',1),
    519 28005 => array('ContourPlot Internal Error: isobarVCrossing: Row index too large (%d)',1),
    520 28006 => array('ContourPlot Internal Error: isobarVCrossing: Col index too large (%d)',1),
    521 28007 => array('ContourPlot interpolation factor is too large (>5)',0),
    522 
    523 /*
    524  * jpgraph_matrix and colormap
    525 */
    526 29201 => array('Min range value must be less or equal to max range value for colormaps',0),
    527 29202 => array('The distance between min and max value is too small for numerical precision',0),
    528 29203 => array('Number of color quantification level must be at least %d',1),
    529 29204 => array('Number of colors (%d) is invalid for this colormap. It must be a number that can be written as: %d + k*%d',3),
    530 29205 => array('Colormap specification out of range. Must be an integer in range [0,%d]',1),
    531 29206 => array('Invalid object added to MatrixGraph',0),
    532 29207 => array('Empty input data specified for MatrixPlot',0),
    533 29208 => array('Unknown side specifiction for matrix labels "%s"',1),
    534 29209 => array('CSIM Target matrix must be the same size as the data matrix (csim=%d x %d, data=%d x %d)',4),
    535 29210 => array('CSIM Target for matrix labels does not match the number of labels (csim=%d, labels=%d)',2),
    536 
    537 
    538 /*
    539 * jpgraph_theme
    540 */
    541 30001 => array("Theme::%s() is not defined. \nPlease make %s(\$graph) function in your theme classs.",2),
    542498
    543499);
  • trunk/client/modules/Elezioni/grafici/lang/prod.inc.php

    r265 r267  
    22/*=======================================================================
    33// File:        PROD.INC.PHP
    4 // Description: Special localization file with the same error messages
     4// Description: Special localization file with the same error messages 
    55//              for all errors.
    66// Created:     2006-02-18
    7 // Ver:         $Id: prod.inc.php 1886 2009-10-01 23:30:16Z ljp $
     7// Ver:         $Id: prod.inc.php 993 2008-03-30 21:17:41Z ljp $
    88//
    9 // Copyright (c) Asial Corporation. All rights reserved.
     9// Copyright (c) Aditus Consulting. All rights reserved.
    1010//========================================================================
    1111*/
     
    2020** Headers already sent error. This is formatted as HTML different since this will be sent back directly as text
    2121*/
    22 10  => array('<table border=1><tr><td><font color=darkred size=4><b>JpGraph Error:</b>
     2210  => array('<table border=1><tr><td><font color=darkred size=4><b>JpGraph Error:</b> 
    2323HTTP headers have already been sent.<br>Caused by output from file <b>%s</b> at line <b>%d</b>.</font></td></tr><tr><td><b>Explanation:</b><br>HTTP headers have already been sent back to the browser indicating the data as text before the library got a chance to send it\'s image HTTP header to this browser. This makes it impossible for the library to send back image data to the browser (since that would be interpretated as text by the browser and show up as junk text).<p>Most likely you have some text in your script before the call to <i>Graph::Stroke()</i>. If this texts gets sent back to the browser the browser will assume that all data is plain text. Look for any text, even spaces and newlines, that might have been sent back to the browser. <p>For example it is a common mistake to leave a blank line before the opening "<b>&lt;?php</b>".</td></tr></table>',2),
    2424
     
    76766031 => array(DEFAULT_ERROR_MESSAGE.'6031',0),
    77776032 => array(DEFAULT_ERROR_MESSAGE.'6032',0),
    78 6033 => array(DEFAULT_ERROR_MESSAGE.'6033',0),
    79787001 => array(DEFAULT_ERROR_MESSAGE.'7001',0),
    80798001 => array(DEFAULT_ERROR_MESSAGE.'8001',0),
     
    12112015010 => array(DEFAULT_ERROR_MESSAGE.'15010',0),
    12212115011 => array(DEFAULT_ERROR_MESSAGE.'15011',0),
    123 15012 => array(DEFAULT_ERROR_MESSAGE.'15012',0),
    12412216001 => array(DEFAULT_ERROR_MESSAGE.'16001',0),
    12512316002 => array(DEFAULT_ERROR_MESSAGE.'16002',0),
     
    15014824002 => array(DEFAULT_ERROR_MESSAGE.'24002',0),
    15114924003 => array(DEFAULT_ERROR_MESSAGE.'24003',0),
    152 24004 => array(DEFAULT_ERROR_MESSAGE.'24004',0),
    15315025001 => array(DEFAULT_ERROR_MESSAGE.'25001',0),
    15415125002 => array(DEFAULT_ERROR_MESSAGE.'25002',0),
     
    27927625128 => array(DEFAULT_ERROR_MESSAGE.'25128',0),
    28027725129 => array(DEFAULT_ERROR_MESSAGE.'25129',0),
    281 25130 => array(DEFAULT_ERROR_MESSAGE.'25130',0),
    282 25131 => array(DEFAULT_ERROR_MESSAGE.'25131',0),
    283 25132 => array(DEFAULT_ERROR_MESSAGE.'25132',0),
    284 25133 => array(DEFAULT_ERROR_MESSAGE.'25133',0),
    285 25500 => array(DEFAULT_ERROR_MESSAGE.'25500',0),
    28627824003 => array(DEFAULT_ERROR_MESSAGE.'24003',0),
    28727924004 => array(DEFAULT_ERROR_MESSAGE.'24004',0),
     
    3293211010 => array(DEFAULT_ERROR_MESSAGE.'1010',0),
    3303221011 => array(DEFAULT_ERROR_MESSAGE.'1011',0),
    331 26000 => array(DEFAULT_ERROR_MESSAGE.'26000',0),
    33232326001 => array(DEFAULT_ERROR_MESSAGE.'26001',0),
    33332426002 => array(DEFAULT_ERROR_MESSAGE.'26002',0),
     
    36235327014 => array(DEFAULT_ERROR_MESSAGE.'27014',0),
    36335427015 => array(DEFAULT_ERROR_MESSAGE.'27015',0),
    364 
    365 28001 => array(DEFAULT_ERROR_MESSAGE.'28001',0),
    366 28002 => array(DEFAULT_ERROR_MESSAGE.'28002',0),
    367 28003 => array(DEFAULT_ERROR_MESSAGE.'28003',0),
    368 28004 => array(DEFAULT_ERROR_MESSAGE.'28004',0),
    369 28005 => array(DEFAULT_ERROR_MESSAGE.'28005',0),
    370 28006 => array(DEFAULT_ERROR_MESSAGE.'28006',0),
    371 28007 => array(DEFAULT_ERROR_MESSAGE.'28007',0),
    372 
    373 29201 => array(DEFAULT_ERROR_MESSAGE.'28001',0),
    374 29202 => array(DEFAULT_ERROR_MESSAGE.'28002',0),
    375 29203 => array(DEFAULT_ERROR_MESSAGE.'28003',0),
    376 29204 => array(DEFAULT_ERROR_MESSAGE.'28004',0),
    377 29205 => array(DEFAULT_ERROR_MESSAGE.'28005',0),
    378 29206 => array(DEFAULT_ERROR_MESSAGE.'28006',0),
    379 29207 => array(DEFAULT_ERROR_MESSAGE.'28007',0),
    380 29208 => array(DEFAULT_ERROR_MESSAGE.'28008',0),
    381 29209 => array(DEFAULT_ERROR_MESSAGE.'28009',0),
    382 29210 => array(DEFAULT_ERROR_MESSAGE.'28010',0),
    383 
    384355);
    385356
Note: See TracChangeset for help on using the changeset viewer.