Changeset 284 for trunk/client


Ignore:
Timestamp:
Apr 21, 2019, 11:49:56 PM (6 years ago)
Author:
roby
Message:
 
Location:
trunk/client
Files:
46 edited

Legend:

Unmodified
Added
Removed
  • trunk/client/modules/Elezioni/grafici.php

    r268 r284  
    605605                echo "</td></tr></table><table><tr><td>";
    606606                # grafico flash
    607 #               if($flash=='1') flash_torta($gruppos,$pre,40,145);
     607                if($flash=='1') flash_torta($gruppos,$pre,40,145);
    608608                                $uno='';
    609609                                foreach($gruppos as $k=>$v) $uno.="- $v";
    610610                                $due='due:';
    611611                                foreach($pre as $k=>$v) $due.="- $v";
    612                                 include("flash_torta($uno,$due,20,70)");
    613612                echo "</td></tr></table>";
    614613               
  • trunk/client/modules/Elezioni/grafici/gd_image.inc.php

    r267 r284  
    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$
     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 $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. All rights reserved.
    99//========================================================================
    1010
    11        
    12 //===================================================
     11require_once 'jpgraph_rgb.inc.php';
     12require_once 'jpgraph_ttf.inc.php';
     13require_once 'imageSmoothArc.php';
     14require_once 'jpgraph_errhandler.inc.php';
     15
     16// Line styles
     17define('LINESTYLE_SOLID',1);
     18define('LINESTYLE_DOTTED',2);
     19define('LINESTYLE_DASHED',3);
     20define('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.
     25if( !DEFINED("DEFAULT_GFORMAT") ) {
     26    define("DEFAULT_GFORMAT","auto");
     27}
     28
     29//========================================================================
    1330// CLASS Image
    14 // Description: Wrapper class with some goodies to form the
    15 // Interface to low level image drawing routines.
    16 //===================================================
     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//=========================================================================
    1737class Image {
    18     public $left_margin=30,$right_margin=30,$top_margin=20,$bottom_margin=30;
    1938    public $img=null;
    20     public $plotwidth=0,$plotheight=0;
    21     public $width=0, $height=0;
    2239    public $rgb=null;
    23     public $current_color,$current_color_name;
    24     public $line_weight=1, $line_style=LINESTYLE_SOLID;
    2540    public $img_format;
    2641    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
    2753    protected $expired=true;
    2854    protected $lastx=0, $lasty=0;
    2955    protected $obs_list=array();
    30     protected $font_size=12,$font_family=FF_FONT1, $font_style=FS_NORMAL;
     56    protected $font_size=12,$font_family=FF_DEFAULT, $font_style=FS_NORMAL;
    3157    protected $font_file='';
    3258    protected $text_halign="left",$text_valign="bottom";
     
    3763    protected $langconv = null ;
    3864    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
    3974    //---------------
    4075    // CONSTRUCTOR
    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();
     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");
    5197    }
    5298
    5399    // Enable interlacing in images
    54100    function SetInterlace($aFlg=true) {
    55         $this->iInterlace=$aFlg;
     101        $this->iInterlace=$aFlg;
    56102    }
    57103
    58104    // Should we use anti-aliasing. Note: This really slows down graphics!
    59105    function SetAntiAliasing($aFlg=true) {
    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         }
     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 ;
    67117    }
    68118
    69119    function CreateRawCanvas($aWidth=0,$aHeight=0) {
    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);                           
     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        }
    96144    }
    97145
    98146    function CloneCanvasH() {
    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    
     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
    105153    function CreateImgCanvas($aWidth=0,$aHeight=0) {
    106154
    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 ;
     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 ;
    132180    }
    133181
    134182    function CopyCanvasH($aToHdl,$aFromHdl,$aToX,$aToY,$aFromX,$aFromY,$aWidth,$aHeight,$aw=-1,$ah=-1) {
    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);
     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);
    144192    }
    145193
    146194    function Copy($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1) {
    147         $this->CopyCanvasH($this->img,$fromImg,$toX,$toY,$fromX,$fromY,
    148                            $toWidth,$toHeight,$fromWidth,$fromHeight);
     195        $this->CopyCanvasH($this->img,$fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight);
    149196    }
    150197
    151198    function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) {
    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         }
     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        }
    177221    }
    178222
    179223    static function GetWidth($aImg=null) {
    180         if( $aImg === null )
    181             $aImg = $this->img;
    182         return imagesx($aImg);
     224        if( $aImg === null ) {
     225            $aImg = $this->img;
     226        }
     227        return imagesx($aImg);
    183228    }
    184229
    185230    static function GetHeight($aImg=null) {
    186         if( $aImg === null )
    187             $aImg = $this->img;
    188         return imagesy($aImg);
    189     }
    190    
     231        if( $aImg === null ) {
     232            $aImg = $this->img;
     233        }
     234        return imagesy($aImg);
     235    }
     236
    191237    static function CreateFromString($aStr) {
    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;
     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;
    197244    }
    198245
    199246    function SetCanvasH($aHdl) {
    200         $this->img = $aHdl;
    201         $this->rgb->img = $aHdl;
     247        $this->img = $aHdl;
     248        $this->rgb->img = $aHdl;
    202249    }
    203250
    204251    function SetCanvasColor($aColor) {
    205         $this->canvascolor = $aColor ;
     252        $this->canvascolor = $aColor ;
    206253    }
    207254
    208255    function SetAlphaBlending($aFlg=true) {
    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                                
     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
    228268    //---------------
    229     // PUBLIC METHODS   
    230        
     269    // PUBLIC METHODS
     270
    231271    function SetFont($family,$style=FS_NORMAL,$size=10) {
    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         }
     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        }
    247290    }
    248291
    249292    // Get the specific height for a text string
    250293    function GetTextHeight($txt="",$angle=0) {
    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        
     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
    281325    // Estimate font height
    282326    function GetFontHeight($angle=0) {
    283         $txt = "XOMg";
    284         return $this->GetTextHeight($txt,$angle);
    285     }
    286        
     327        $txt = "XOMg";
     328        return $this->GetTextHeight($txt,$angle);
     329    }
     330
    287331    // Approximate font width with width of letter "O"
    288332    function GetFontWidth($angle=0) {
    289         $txt = 'O';
    290         return $this->GetTextWidth($txt,$angle);
    291     }
    292        
    293     // Get actual width of text in absolute pixels
     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.
    294340    function GetTextWidth($txt,$angle=0) {
    295341
    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        
     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
    339386    // Draw text with a box around it
    340387    function StrokeBoxedText($x,$y,$txt,$dir=0,$fcolor="white",$bcolor="black",
    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       
     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;
     442            }
     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;
     448            }
     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
    414625    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));
     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));
    444659            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             }
     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            }
    473686            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 
    482             }
    483             $aBoundingBox=array(round($x),round($y),round($x),round($y-$h),round($x+$w),round($y-$h),round($x+$w),round($y));
    484         }
     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        }
    485698    }
    486699
    487700    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 
     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
    500816    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;
     817        $bbox = $this->imagettfbbox_fixed($this->font_size,$aAngle,$this->font_file,$aTxt);
     818         return $bbox;
    507819    }
    508820
    509821    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;
     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;
    560872    }
    561873
    562874    function GetBBoxHeight($aTxt,$aAngle=0) {
    563         $box = $this->GetBBoxTTF($aTxt,$aAngle);
    564         return $box[1]-$box[7]+1;
     875        $box = $this->GetBBoxTTF($aTxt,$aAngle);
     876        return abs($box[7]-$box[1]);
    565877    }
    566878
    567879    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
     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
    621956            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();
    648             }
    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        
     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
    7441086    function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) {
    7451087
    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        
     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
    7661110    function SetMargin($lm,$rm,$tm,$bm) {
    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         }
     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        }
    7771126    }
    7781127
    7791128    function SetTransparent($color) {
    780         imagecolortransparent ($this->img,$this->rgb->allocate($color));
    781     }
    782        
     1129        imagecolortransparent ($this->img,$this->rgb->allocate($color));
     1130    }
     1131
    7831132    function SetColor($color,$aAlpha=0) {
    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        
     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
    7941143    function PushColor($color) {
    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        
     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
    8061155    function PopColor() {
    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        
     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
    8141164    function SetLineWeight($weight) {
    815         imagesetthickness($this->img,$weight);
    816         $this->line_weight = $weight;
    817     }
    818        
     1165        $old = $this->line_weight;
     1166        imagesetthickness($this->img,$weight);
     1167        $this->line_weight = $weight;
     1168        return $old;
     1169    }
     1170
    8191171    function SetStartPoint($x,$y) {
    820         $this->lastx=round($x);
    821         $this->lasty=round($y);
    822     }
    823        
     1172        $this->lastx=round($x);
     1173        $this->lasty=round($y);
     1174    }
     1175
    8241176    function Arc($cx,$cy,$w,$h,$s,$e) {
    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    
     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
    8331183    function FilledArc($xc,$yc,$w,$h,$s,$e,$style='') {
    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         }
     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        }
    8421194    }
    8431195
    8441196    function FilledCakeSlice($cx,$cy,$w,$h,$s,$e) {
    845         $this->CakeSlice($cx,$cy,$w,$h,$s,$e,$this->current_color_name);
     1197        $this->CakeSlice($cx,$cy,$w,$h,$s,$e,$this->current_color_name);
    8461198    }
    8471199
    8481200    function CakeSlice($xc,$yc,$w,$h,$s,$e,$fillcolor="",$arccolor="") {
    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         }
     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        }
    8741232    }
    8751233
    8761234    function Ellipse($xc,$yc,$w,$h) {
    877         $this->Arc($xc,$yc,$w,$h,0,360);
    878     }
    879                        
     1235        $this->Arc($xc,$yc,$w,$h,0,360);
     1236    }
     1237
    8801238    function Circle($xc,$yc,$r) {
    881         imageellipse($this->img,round($xc),round($yc),$r*2,$r*2,$this->current_color);
    882     }
    883        
     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
    8841244    function FilledCircle($xc,$yc,$r) {
    885         imagefilledellipse($this->img,round($xc),round($yc),2*$r,2*$r,$this->current_color);
    886     }
    887        
     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
    8881249    // Linear Color InterPolation
    8891250    function lip($f,$t,$p) {
    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);
     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);
    8951256    }
    8961257
    8971258    // Set line style dashed, dotted etc
    8981259    function SetLineStyle($s) {
    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        
     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
    9181282    // Same as Line but take the line_style into account
    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        
     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
    9491331    function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) {
    9501332
    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     }
     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    }
    9731391
    9741392    function Line($x1,$y1,$x2,$y2) {
    9751393
    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;             
     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;
    9861405    }
    9871406
    9881407    function Polygon($p,$closed=FALSE,$fast=FALSE) {
    9891408
    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        
     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
    10171436    function FilledPolygon($pts) {
    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        
     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
    10271451    function Rectangle($xl,$yu,$xr,$yl) {
    1028         $this->Polygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl,$xl,$yu));
    1029     }
    1030        
     1452        $this->Polygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl,$xl,$yu));
     1453    }
     1454
    10311455    function FilledRectangle($xl,$yu,$xr,$yl) {
    1032         $this->FilledPolygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl));
     1456        $this->FilledPolygon(array($xl,$yu,$xr,$yu,$xr,$yl,$xl,$yl));
    10331457    }
    10341458
    10351459    function FilledRectangle2($xl,$yu,$xr,$yl,$color1,$color2,$style=1) {
    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
     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
    10661490        // the reactangle has no fill color
    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         }
     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        }
    10801520    }
    10811521
    10821522    function FilledRoundedRectangle($xt,$yt,$xr,$yl,$r=5) {
    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);
     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);
    11351575    }
    11361576
    11371577    function FilledBevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='darkgray@0.4') {
    1138         $this->FilledRectangle($x1,$y1,$x2,$y2);
    1139         $this->Bevel($x1,$y1,$x2,$y2,$depth,$color1,$color2);
     1578        $this->FilledRectangle($x1,$y1,$x2,$y2);
     1579        $this->Bevel($x1,$y1,$x2,$y2,$depth,$color1,$color2);
    11401580    }
    11411581
    11421582    function Bevel($x1,$y1,$x2,$y2,$depth=2,$color1='white@0.4',$color2='black@0.5') {
    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();
     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();
    11561596    }
    11571597
    11581598    function StyleLineTo($x,$y) {
    1159         $this->StyleLine($this->lastx,$this->lasty,$x,$y);
    1160         $this->lastx=$x;
    1161         $this->lasty=$y;
    1162     }
    1163        
     1599        $this->StyleLine($this->lastx,$this->lasty,$x,$y);
     1600        $this->lastx=$x;
     1601        $this->lasty=$y;
     1602    }
     1603
    11641604    function LineTo($x,$y) {
    1165         $this->Line($this->lastx,$this->lasty,$x,$y);
    1166         $this->lastx=$x;
    1167         $this->lasty=$y;
    1168     }
    1169        
     1605        $this->Line($this->lastx,$this->lasty,$x,$y);
     1606        $this->lastx=$x;
     1607        $this->lasty=$y;
     1608    }
     1609
    11701610    function Point($x,$y) {
    1171         imagesetpixel($this->img,round($x),round($y),$this->current_color);
    1172     }
    1173        
     1611        imagesetpixel($this->img,round($x),round($y),$this->current_color);
     1612    }
     1613
    11741614    function Fill($x,$y) {
    1175         imagefill($this->img,round($x),round($y),$this->current_color);
     1615        imagefill($this->img,round($x),round($y),$this->current_color);
    11761616    }
    11771617
    11781618    function FillToBorder($x,$y,$aBordColor) {
    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);
     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);
    11841624    }
    11851625
    11861626    function SetExpired($aFlg=true) {
    1187         $this->expired = $aFlg;
    1188     }
    1189        
     1627        $this->expired = $aFlg;
     1628    }
     1629
    11901630    // Generate image header
    11911631    function Headers() {
    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");
     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");
    12171656    }
    12181657
    12191658    // Adjust image quality for formats that allow this
    12201659    function SetQuality($q) {
    1221         $this->quality = $q;
    1222     }
    1223        
     1660        $this->quality = $q;
     1661    }
     1662
    12241663    // Stream image to browser or to file
    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.");
     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                                }
    12401677               
    1241             }
    1242         }
    1243     }
    1244                
    1245     // Clear resource tide up by image
     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
    12461711    function Destroy() {
    1247         imagedestroy($this->img);
    1248     }
    1249        
     1712        imagedestroy($this->img);
     1713    }
     1714
    12501715    // Specify image format. Note depending on your installation
    12511716    // of PHP not all formats may be supported.
    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     }   
     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
    12961941} // CLASS
    12971942
     
    13031948class RotImage extends Image {
    13041949    public $a=0;
    1305     public $dx=0,$dy=0,$transx=0,$transy=0; 
     1950    public $dx=0,$dy=0,$transx=0,$transy=0;
    13061951    private $m=array();
    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        
     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
    13151960    function SetCenter($dx,$dy) {
    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        
     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
    13241969    function SetTranslation($dx,$dy) {
    1325         $old = array($this->transx,$this->transy);
    1326         $this->transx = $dx;
    1327         $this->transy = $dy;
    1328         return $old;
     1970        $old = array($this->transx,$this->transy);
     1971        $this->transx = $dx;
     1972        $this->transy = $dy;
     1973        return $old;
    13291974    }
    13301975
    13311976    function UpdateRotMatrice()  {
    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 ;
     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 ;
    13421987    }
    13431988
    13441989    function SetAngle($a) {
    1345         $tmp = $this->a;
    1346         $this->a = $a;
    1347         $this->UpdateRotMatrice();
    1348         return $tmp;
     1990        $tmp = $this->a;
     1991        $this->a = $a;
     1992        $this->UpdateRotMatrice();
     1993        return $tmp;
    13491994    }
    13501995
    13511996    function Circle($xc,$yc,$r) {
    1352         list($xc,$yc) = $this->Rotate($xc,$yc);
    1353         parent::Circle($xc,$yc,$r);
     1997        list($xc,$yc) = $this->Rotate($xc,$yc);
     1998        parent::Circle($xc,$yc,$r);
    13541999    }
    13552000
    13562001    function FilledCircle($xc,$yc,$r) {
    1357         list($xc,$yc) = $this->Rotate($xc,$yc);
    1358         parent::FilledCircle($xc,$yc,$r);
    1359     }
    1360 
    1361        
     2002        list($xc,$yc) = $this->Rotate($xc,$yc);
     2003        parent::FilledCircle($xc,$yc,$r);
     2004    }
     2005
     2006
    13622007    function 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);
     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);
    13672012    }
    13682013
    13692014    function FilledArc($xc,$yc,$w,$h,$s,$e,$style='') {
    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);
     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);
    13742019    }
    13752020
    13762021    function SetMargin($lm,$rm,$tm,$bm) {
    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        
     2022        parent::SetMargin($lm,$rm,$tm,$bm);
     2023        $this->UpdateRotMatrice();
     2024    }
     2025
    13832026    function Rotate($x,$y) {
    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        
     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
    13952038    function CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth=-1,$fromHeight=-1,$aMix=100) {
    1396         list($toX,$toY) = $this->Rotate($toX,$toY);
    1397         parent::CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight,$aMix);
     2039        list($toX,$toY) = $this->Rotate($toX,$toY);
     2040        parent::CopyMerge($fromImg,$toX,$toY,$fromX,$fromY,$toWidth,$toHeight,$fromWidth,$fromHeight,$aMix);
    13982041
    13992042    }
    14002043
    14012044    function ArrRotate($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;
     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;
    14082051    }
    14092052
    14102053    function DashedLine($x1,$y1,$x2,$y2,$dash_length=1,$dash_space=4) {
    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        
     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
    14162059    function 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);
     2060        list($x1,$y1) = $this->Rotate($x1,$y1);
     2061        list($x2,$y2) = $this->Rotate($x2,$y2);
     2062        parent::Line($x1,$y1,$x2,$y2);
    14202063    }
    14212064
    14222065    function Rectangle($x1,$y1,$x2,$y2) {
    1423         // Rectangle uses Line() so it will be rotated through that call
    1424         parent::Rectangle($x1,$y1,$x2,$y2);
    1425     }
    1426        
     2066        // Rectangle uses Line() so it will be rotated through that call
     2067        parent::Rectangle($x1,$y1,$x2,$y2);
     2068    }
     2069
    14272070    function FilledRectangle($x1,$y1,$x2,$y2) {
    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        
     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
    14342077    function Polygon($pnts,$closed=FALSE,$fast=FALSE) {
    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        
     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
    14442088    function FilledPolygon($pnts) {
    1445         parent::FilledPolygon($this->ArrRotate($pnts));
    1446     }
    1447        
     2089        parent::FilledPolygon($this->ArrRotate($pnts));
     2090    }
     2091
    14482092    function Point($x,$y) {
    1449         list($xp,$yp) = $this->Rotate($x,$y);
    1450         parent::Point($xp,$yp);
    1451     }
    1452        
     2093        list($xp,$yp) = $this->Rotate($x,$y);
     2094        parent::Point($xp,$yp);
     2095    }
     2096
    14532097    function StrokeText($x,$y,$txt,$dir=0,$paragraph_align="left",$debug=false) {
    1454         list($xp,$yp) = $this->Rotate($x,$y);
    1455         return parent::StrokeText($xp,$yp,$txt,$dir,$paragraph_align,$debug);
     2098        list($xp,$yp) = $this->Rotate($x,$y);
     2099        return parent::StrokeText($xp,$yp,$txt,$dir,$paragraph_align,$debug);
    14562100    }
    14572101}
    14582102
    1459 //===================================================
     2103//=======================================================================
    14602104// CLASS ImgStreamCache
    1461 // Description: Handle caching of graphs to files
    1462 //===================================================
     2105// Description: Handle caching of graphs to files. All image output goes
     2106//              through this class
     2107//=======================================================================
    14632108class ImgStreamCache {
    1464     private $cache_dir, $img=null, $timeout=0;  // Infinite timeout
     2109    private $cache_dir, $timeout=0;  // Infinite timeout
    14652110    //---------------
    14662111    // CONSTRUCTOR
    1467     function ImgStreamCache($aImg, $aCacheDir=CACHE_DIR) {
    1468         $this->img = $aImg;
    1469         $this->cache_dir = $aCacheDir;
    1470     }
    1471 
    1472 //---------------
    1473 // PUBLIC METHODS       
     2112    function __construct($aCacheDir=CACHE_DIR) {
     2113        $this->cache_dir = $aCacheDir;
     2114    }
     2115
     2116    //---------------
     2117    // PUBLIC METHODS
    14742118
    14752119    // Specify a timeout (in minutes) for the file. If the file is older then the
     
    14782122    // timeout is set to -1 this is the same as infinite small timeout
    14792123    function SetTimeout($aTimeout) {
    1480         $this->timeout=$aTimeout;       
    1481     }
    1482        
     2124        $this->timeout=$aTimeout;
     2125    }
     2126
    14832127    // Output image to browser and also write it to the cache
    14842128    function PutAndStream($aImage,$aCacheFileName,$aInline,$aStrokeFileName) {
    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        
     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
    15672268    // Check if a given image is in cache and in that case
    15682269    // pass it directly on to web browser. Return false if the
    15692270    // image file doesn't exist or exists but is to old
    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        
     2271    function GetAndStream($aImage,$aCacheFileName) {
     2272        if( $this->Isvalid($aCacheFileName) ) {
     2273            $this->StreamImgFile($aImage,$aCacheFileName);
     2274        }
     2275        else {
     2276            return false;
     2277        }
     2278    }
     2279
    15902280    //---------------
    1591     // PRIVATE METHODS 
     2281    // PRIVATE METHODS
    15922282    // Create all necessary directories in a path
    15932283    function MakeDirs($aFile) {
    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     }   
     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    }
    16162310} // CLASS Cache
    16172311
    1618 
    16192312?>
  • trunk/client/modules/Elezioni/grafici/imgdata_balls.inc.php

    r267 r284  
    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 860 2007-03-23 19:16:19Z 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 1106 2009-02-22 20:16:35Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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 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==' ;
     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==' ;
    10581058    }
    10591059}
  • trunk/client/modules/Elezioni/grafici/imgdata_bevels.inc.php

    r267 r284  
    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 860 2007-03-23 19:16:19Z 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 1106 2009-02-22 20:16:35Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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 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             '==' ;
     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     '==' ;
    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

    r267 r284  
    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 860 2007-03-23 19:16:19Z 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 1106 2009-02-22 20:16:35Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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 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=' ;
     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=' ;
    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

    r267 r284  
    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 860 2007-03-23 19:16:19Z 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 1106 2009-02-22 20:16:35Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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 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' ;
     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' ;
    514514    }
    515515}
  • trunk/client/modules/Elezioni/grafici/imgdata_squares.inc.php

    r267 r284  
    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 860 2007-03-23 19:16:19Z 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 1106 2009-02-22 20:16:35Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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

    r267 r284  
    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 860 2007-03-23 19:16:19Z 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 1106 2009-02-22 20:16:35Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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 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==' ;
     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==' ;
    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

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
     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 $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. All rights reserved.
    99//========================================================================
    1010
    1111
    12 
    1312//------------------------------------------------------------------------
    14 // Directories for cache and font directory. 
     13// Directories for cache and font directory.
    1514//
    1615// CACHE_DIR:
     
    2928//   CACHE_DIR /tmp/jpgraph_cache/
    3029//   TTF_DIR   /usr/share/fonts/truetype/
    31 //   MBTTF_DIR /usr/share/fonts/ja/TrueType/
     30//   MBTTF_DIR /usr/share/fonts/truetype/
    3231//
    33 define("TTF_DIR","/usr/share/fonts/truetype/ttf-dejavu/");
    3432// WINDOWS:
    3533//   CACHE_DIR $SERVER_TEMP/jpgraph_cache/
     
    3836//
    3937//------------------------------------------------------------------------
    40 // define("CACHE_DIR","/tmp/jpgraph_cache/");
    41 // define("TTF_DIR","/usr/share/fonts/truetype/");
    42 // define("MBTTF_DIR","/usr/share/fonts/ja/TrueType/");
     38// define('CACHE_DIR','/tmp/jpgraph_cache/');
     39// define('TTF_DIR','/usr/share/fonts/TrueType/');
     40// define('MBTTF_DIR','/usr/share/fonts/TrueType/');
    4341
    4442//-------------------------------------------------------------------------
     
    4644// using the cache.
    4745// The directory must be the filesysystem name as seen by PHP
    48 // and the 'http' version must be the same directory but as 
    49 // seen by the HTTP server relative to the 'htdocs' ddirectory. 
     46// and the 'http' version must be the same directory but as
     47// seen by the HTTP server relative to the 'htdocs' ddirectory.
    5048// If a relative path is specified it is taken to be relative from where
    5149// the image script is executed.
    52 // Note: The default setting is to create a subdirectory in the 
     50// Note: The default setting is to create a subdirectory in the
    5351// directory from where the image script is executed and store all files
    5452// there. As ususal this directory must be writeable by the PHP process.
    55 define("CSIMCACHE_DIR","csimcache/");
    56 define("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
    65 define('CHINESE_TTF_FONT','bkai00mp.ttf');
    66 
    67 // Special unicode greek language support
    68 define("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
    72 define("GREEK_FROM_WINDOWS",false);
    73 
    74 // Special unicode cyrillic language support
    75 define("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
    80 define("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 //
    107 define('LANGUAGE_CHARSET', null);
    108 
    109 // Japanese TrueType font used with FF_MINCHO, FF_PMINCHO, FF_GOTHIC, FF_PGOTHIC
    110 define('MINCHO_TTF_FONT','ipam.ttf');
    111 define('PMINCHO_TTF_FONT','ipamp.ttf');
    112 define('GOTHIC_TTF_FONT','ipag.ttf');
    113 define('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.
    118 define('ASSUME_EUCJP_ENCODING',false);
     53define('CSIMCACHE_DIR','csimcache/');
     54define('CSIMCACHE_HTTP_DIR','csimcache/');
    11955
    12056//------------------------------------------------------------------------
     
    12864define('DEFAULT_ERR_LOCALE','en');
    12965
    130 // Deafult graphic format set to "auto" which will automatically
     66// Deafult graphic format set to 'auto' which will automatically
    13167// choose the best available format in the order png,gif,jpeg
    13268// (The supported format depends on what your PHP installation supports)
    133 define("DEFAULT_GFORMAT","auto");
     69define('DEFAULT_GFORMAT','auto');
    13470
    13571// Should the cache be used at all? By setting this to false no
    136 // files will be generated in the cache directory. 
     72// files will be generated in the cache directory.
    13773// The difference from READ_CACHE being that setting READ_CACHE to
    13874// false will still create the image in the cache directory
    13975// just not use it. By setting USE_CACHE=false no files will even
    14076// be generated in the cache directory.
    141 define("USE_CACHE",false);
     77define('USE_CACHE',false);
    14278
    143 // Should we try to find an image in the cache before generating it? 
     79// Should we try to find an image in the cache before generating it?
    14480// Set this define to false to bypass the reading of the cache and always
    145 // regenerate the image. Note that even if reading the cache is 
     81// regenerate the image. Note that even if reading the cache is
    14682// disabled the cached will still be updated with the newly generated
    147 // image. Set also "USE_CACHE" below.
    148 define("READ_CACHE",true);
     83// image. Set also 'USE_CACHE' below.
     84define('READ_CACHE',true);
    14985
    15086// Determine if the error handler should be image based or purely
    15187// text based. Image based makes it easier since the script will
    15288// always return an image even in case of errors.
    153 define("USE_IMAGE_ERROR_HANDLER",true);
     89define('USE_IMAGE_ERROR_HANDLER',true);
    15490
    155 // Should the library examin the global php_errmsg string and convert
     91// Should the library examine the global php_errmsg string and convert
    15692// any error in it to a graphical representation. This is handy for the
    15793// occasions when, for example, header files cannot be found and this results
    158 // in the graph not being created and just a "red-cross" image would be seen.
     94// in the graph not being created and just a 'red-cross' image would be seen.
    15995// This should be turned off for a production site.
    160 define("CATCH_PHPERRMSG",true);
     96define('CATCH_PHPERRMSG',true);
    16197
    16298// Determine if the library should also setup the default PHP
    16399// error handler to generate a graphic error mesage. This is useful
    164100// during development to be able to see the error message as an image
    165 // instead as a "red-cross" in a page where an image is expected.
    166 define("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.
    177 define("USE_APPROX_COLORS",true);
     101// instead as a 'red-cross' in a page where an image is expected.
     102define('INSTALL_PHP_ERR_HANDLER',false);
    178103
    179104// Should usage of deprecated functions and parameters give a fatal error?
    180105// (Useful to check if code is future proof.)
    181 define("ERR_DEPRECATED",true);
     106define('ERR_DEPRECATED',true);
    182107
    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
    186 define("BRAND_TIMING",false);
    187 
    188 // What format should be used for the timing string?
    189 define("BRAND_TIME_FORMAT","(%01.3fs)");
     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.
     115define('USE_LIBRARY_IMAGETTFBBOX',true);
    190116
    191117//------------------------------------------------------------------------
     
    194120
    195121// What group should the cached file belong to
    196 // (Set to "" will give the default group for the "PHP-user")
     122// (Set to '' will give the default group for the 'PHP-user')
    197123// Please note that the Apache user must be a member of the
    198124// specified group since otherwise it is impossible for Apache
    199125// to set the specified group.
    200 define("CACHE_FILE_GROUP","wwwadmin");
     126define('CACHE_FILE_GROUP','www');
    201127
    202128// What permissions should the cached file have
    203 // (Set to "" will give the default persmissions for the "PHP-user")
    204 define("CACHE_FILE_MOD",0664);
     129// (Set to '' will give the default persmissions for the 'PHP-user')
     130define('CACHE_FILE_MOD',0664);
    205131
    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
    210 define("USE_BRESENHAM",false);
     132// Default theme class name
     133define('DEFAULT_THEME_CLASS', 'UniversalTheme');
    211134
    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.
    215 define("_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.
    220 define("_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.
    225 define("_IMG_HANDLER","__handle");
    226 
     135define('SUPERSAMPLING', true);
     136define('SUPERSAMPLING_SCALE', 1);
    227137
    228138?>
  • trunk/client/modules/Elezioni/grafici/jpgraph.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
     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 $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. All rights reserved.
    99//========================================================================
    1010
     
    1616require_once('jpgraph_text.inc.php');
    1717require_once('jpgraph_legend.inc.php');
     18require_once('jpgraph_theme.inc.php');
     19require_once('gd_image.inc.php');
    1820
    1921// Version info
    20 define('JPG_VERSION','2.3.5-dev');
     22define('JPG_VERSION','4.2.6');
    2123
    2224// Minimum required PHP version
    2325define('MIN_PHPVERSION','5.1.0');
    2426
    25 // Should the image be a truecolor image?
    26 define('USE_TRUECOLOR',true);
    27 
    28 //------------------------------------------------------------------------
    29 // Automatic settings of path for cache and font directory
    30 // if they have not been previously specified
    31 //------------------------------------------------------------------------
    32 if(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 }
    48 elseif( !defined('CACHE_DIR') ) {
    49     define('CACHE_DIR', '');
    50 }
    51 
    52 if (!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 
    68 if (!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 
     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.
     30define('_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.
     35define('_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.
     40define('_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.
     44define('_IMG_AUTO','auto');
    8845
    8946// Tick density
     
    9350define("TICKD_VERYSPARSE",4);
    9451
    95 // Side for ticks and labels. 
     52// Side for ticks and labels.
    9653define("SIDE_LEFT",-1);
    9754define("SIDE_RIGHT",1);
     
    156113define("HORIZONTAL",0);
    157114
    158 
    159115// Axis styles for scientific style axis
    160116define('AXSTYLE_SIMPLE',1);
     
    176132define('TITLEBKG_FILLSTYLE_SOLID',3);
    177133
     134// Styles for axis labels background
     135define('LABELBKG_NONE',0);
     136define('LABELBKG_XAXIS',1);
     137define('LABELBKG_YAXIS',2);
     138define('LABELBKG_XAXISFULL',3);
     139define('LABELBKG_YAXISFULL',4);
     140define('LABELBKG_XYFULL',5);
     141define('LABELBKG_XY',6);
     142
     143
    178144// Style for background gradient fills
    179145define('BGRAD_FRAME',1);
     
    191157define('SKEW3D_RIGHT',3);
    192158
    193 // Line styles
    194 define('LINESTYLE_SOLID',1);
    195 define('LINESTYLE_DOTTED',2);
    196 define('LINESTYLE_DASHED',3);
    197 define('LINESTYLE_LONGDASH',4);
    198 
    199159// For internal use only
    200160define("_JPG_DEBUG",false);
     
    202162define("_FORCE_IMGDIR",'/tmp/jpgimg/');
    203163
    204 require_once('gd_image.inc.php');
    205 
    206 function 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;
     164
     165//
     166// Automatic settings of path for cache and font directory
     167// if they have not been previously specified
     168//
     169if(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}
     185elseif( !defined('CACHE_DIR') ) {
     186    define('CACHE_DIR', '');
     187}
     188
     189//
     190// Setup path for western/latin TTF fonts
     191//
     192if (!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//
     211if (!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//
     230function CheckPHPVersion($aMinVersion) {
     231    list($majorC, $minorC, $editC) = preg_split('/[\/.-]/', PHP_VERSION);
     232    list($majorR, $minorR, $editR) = preg_split('/[\/.-]/', $aMinVersion);
     233
    212234    if ($majorC < $majorR) return false;
    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;
     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
    218244    return true;
    219245}
     
    227253}
    228254
    229 
    230255//
    231256// Make GD sanity check
     
    233258if( !function_exists("imagetypes") || !function_exists('imagecreatefromstring') ) {
    234259    JpGraphError::RaiseL(25001);
    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)");
     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)");
    236261}
    237262
     
    242267    // Respect current error level
    243268    if( $errno & error_reporting() ) {
    244         JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg);
     269        JpGraphError::RaiseL(25003,basename($filename),$linenum,$errmsg);
    245270    }
    246271}
     
    251276
    252277//
    253 //Check if there were any warnings, perhaps some wrong includes by the
    254 //user
     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
    255281//
    256 if( isset($GLOBALS['php_errormsg']) && CATCH_PHPERRMSG &&
    257     !preg_match('/|Deprecated|/i', $GLOBALS['php_errormsg']) ) {
     282if( isset($GLOBALS['php_errormsg']) && CATCH_PHPERRMSG && !preg_match('/|Deprecated|/i', $GLOBALS['php_errormsg']) ) {
    258283    JpGraphError::RaiseL(25004,$GLOBALS['php_errormsg']);
    259284}
    260285
    261 
    262286// Useful mathematical function
    263287function sign($a) {return $a >= 0 ? 1 : -1;}
    264288
     289//
    265290// Utility function to generate an image name based on the filename we
    266291// are running from and assuming we use auto detection of graphic format
    267292// (top level), i.e it is safe to call this function
    268293// from a script that uses JpGraph
     294//
    269295function GenImgName() {
    270296    // Determine what format we should use when we save the images
    271297    $supported = imagetypes();
    272     if( $supported & IMG_PNG )     $img_format="png";
     298    if( $supported & IMG_PNG )    $img_format="png";
    273299    elseif( $supported & IMG_GIF ) $img_format="gif";
    274300    elseif( $supported & IMG_JPG ) $img_format="jpeg";
     
    277303
    278304
    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.");
     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    }
    282309    $fname = basename($_SERVER['PHP_SELF']);
    283310    if( !empty($_SERVER['QUERY_STRING']) ) {
    284         $q = @$_SERVER['QUERY_STRING'];
    285         $fname .= '_'.preg_replace("/\W/", "_", $q).'.'.$img_format;
     311        $q = @$_SERVER['QUERY_STRING'];
     312        $fname .= '_'.preg_replace("/\W/", "_", $q).'.'.$img_format;
    286313    }
    287314    else {
    288         $fname = substr($fname,0,strlen($fname)-4).'.'.$img_format;
     315        $fname = substr($fname,0,strlen($fname)-4).'.'.$img_format;
    289316    }
    290317    return $fname;
    291318}
    292 
    293319
    294320//===================================================
     
    299325//===================================================
    300326class JpgTimer {
    301     private $start, $idx;       
    302 //---------------
    303 // CONSTRUCTOR
    304     function JpgTimer() {
    305         $this->idx=0;
    306     }
    307 
    308 //---------------
    309 // PUBLIC METHODS       
     327    private $start, $idx;
     328
     329    function __construct() {
     330        $this->idx=0;
     331    }
    310332
    311333    // Push a new timer start on stack
    312334    function Push() {
    313         list($ms,$s)=explode(" ",microtime()); 
    314         $this->start[$this->idx++]=floor($ms*1000) + 1000*$s;   
     335        list($ms,$s)=explode(" ",microtime());
     336        $this->start[$this->idx++]=floor($ms*1000) + 1000*$s;
    315337    }
    316338
     
    318340    // current time
    319341    function Pop() {
    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];
     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];
    325347    }
    326348} // Class
    327349
    328 $gJpgBrandTiming = BRAND_TIMING;
    329350//===================================================
    330351// CLASS DateLocale
     
    332353//===================================================
    333354class DateLocale {
    334  
     355
    335356    public $iLocale = 'C'; // environmental locale be used by default
    336357    private $iDayAbb = null, $iShortDay = null, $iShortMonth = null, $iMonthName = null;
    337358
    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       
     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
    352367    function Set($aLocale) {
    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;
     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;
    396411    }
    397412
    398413
    399414    function GetDayAbb() {
    400         return $this->iDayAbb[$this->iLocale];
    401     }
    402        
     415        return $this->iDayAbb[$this->iLocale];
     416    }
     417
    403418    function GetShortDay() {
    404         return $this->iShortDay[$this->iLocale];
     419        return $this->iShortDay[$this->iLocale];
    405420    }
    406421
    407422    function GetShortMonth() {
    408         return $this->iShortMonth[$this->iLocale];
    409     }
    410        
     423        return $this->iShortMonth[$this->iLocale];
     424    }
     425
    411426    function GetShortMonthName($aNbr) {
    412         return $this->iShortMonth[$this->iLocale][$aNbr];
     427        return $this->iShortMonth[$this->iLocale][$aNbr];
    413428    }
    414429
    415430    function GetLongMonthName($aNbr) {
    416         return $this->iMonthName[$this->iLocale][$aNbr];
     431        return $this->iMonthName[$this->iLocale][$aNbr];
    417432    }
    418433
    419434    function GetMonth() {
    420         return $this->iMonthName[$this->iLocale];
     435        return $this->iMonthName[$this->iLocale];
    421436    }
    422437}
    423438
     439// Global object handlers
    424440$gDateLocale = new DateLocale();
    425441$gJpgDateLocale = new DateLocale();
     
    432448    public $iLeftMargin = 3, $iRightMargin = 3, $iBottomMargin = 3 ;
    433449    public $left,$center,$right;
    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');
     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;
    442464    }
    443465
    444466    function SetMargin($aLeft=3,$aRight=3,$aBottom=3) {
    445         $this->iLeftMargin = $aLeft;
    446         $this->iRightMargin = $aRight;
    447         $this->iBottomMargin = $aBottom;
     467        $this->iLeftMargin = $aLeft;
     468        $this->iRightMargin = $aRight;
     469        $this->iBottomMargin = $aBottom;
    448470    }
    449471
    450472    function Stroke($aImg) {
    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);
     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);
    463488    }
    464489}
     
    470495//===================================================
    471496class Graph {
    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)
     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)
    476501    public $ynplots=array();
    477     public $xscale=null;                // X Scale object (could be instance of LinearScale or LogScale
     502    public $xscale=null;  // X Scale object (could be instance of LinearScale or LogScale
    478503    public $yscale=null,$y2scale=null, $ynscale=array();
    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
     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
    494519    public $lines=null, $y2lines=null;
    495520    public $bands=null, $y2bands=null;
    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";
     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";
    498523    public $background_image_bright=0,$background_image_contr=0,$background_image_sat=0;
    499524    public $background_image_xpos=0,$background_image_ypos=0;
     
    501526    public $inline;
    502527    public $showcsim=0,$csimcolor="red";//debug stuff, draw the csim boundaris on the image if <>0
    503     public $grid_depth=DEPTH_BACK;      // Draw grid under all plots as default
     528    public $grid_depth=DEPTH_BACK; // Draw grid under all plots as default
    504529    public $iAxisStyle = AXSTYLE_SIMPLE;
    505530    public $iCSIMdisplay=false,$iHasStroked = false;
     
    511536    public $bkg_gradtype=-1,$bkg_gradstyle=BGRAD_MARGIN;
    512537    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
    513541    public $titlebackground = false;
    514542    public $titlebackground_color = 'lightblue',
    515         $titlebackground_style = 1,
    516         $titlebackground_framecolor = 'blue',
    517         $titlebackground_framestyle = 2,
    518         $titlebackground_frameweight = 1,
    519         $titlebackground_bevelheight = 3 ;
     543           $titlebackground_style = 1,
     544           $titlebackground_framecolor,
     545           $titlebackground_framestyle,
     546           $titlebackground_frameweight,
     547           $titlebackground_bevelheight;
    520548    public $titlebkg_fillstyle=TITLEBKG_FILLSTYLE_SOLID;
    521549    public $titlebkg_scolor1='black',$titlebkg_scolor2='white';
    522     public $framebevel = false, $framebeveldepth = 2 ;
    523     public $framebevelborder = false, $framebevelbordercolor='black';
    524     public $framebevelcolor1='white@0.4', $framebevelcolor2='black@0.4';
     550    public $framebevel, $framebeveldepth;
     551    public $framebevelborder, $framebevelbordercolor;
     552    public $framebevelcolor1, $framebevelcolor2;
    525553    public $background_image_mix=100;
    526554    public $background_cflag = '';
     
    528556    public $background_cflag_mix = 100;
    529557    public $iImgTrans=false,
    530         $iImgTransHorizon = 100,$iImgTransSkewDist=150,
    531         $iImgTransDirection = 1, $iImgTransMinSize = true,
    532         $iImgTransFillColor='white',$iImgTransHighQ=false,
    533         $iImgTransBorder=false,$iImgTransHorizonPos=0.5;
     558           $iImgTransHorizon = 100,$iImgTransSkewDist=150,
     559           $iImgTransDirection = 1, $iImgTransMinSize = true,
     560           $iImgTransFillColor='white',$iImgTransHighQ=false,
     561           $iImgTransBorder=false,$iImgTransHorizonPos=0.5;
    534562    public $legend;
     563    public $graph_theme;
    535564    protected $iYAxisDeltaPos=50;
    536565    protected $iIconDepth=DEPTH_BACK;
    537566    protected $iAxisLblBgType = 0,
    538         $iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black',
    539         $iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black';
     567              $iXAxisLblBgFillColor = 'lightgray', $iXAxisLblBgColor = 'black',
     568              $iYAxisLblBgFillColor = 'lightgray', $iYAxisLblBgColor = 'black';
    540569    protected $iTables=NULL;
    541570
    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    
     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
    614679    // Enable final image perspective transformation
    615680    function Set3DPerspective($aDir=1,$aHorizon=100,$aSkewDist=120,$aQuality=false,$aFillColor='#FFFFFF',$aBorder=false,$aMinSize=true,$aHorizonPos=0.5) {
    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;
     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;
    625690    }
    626691
    627692    function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    628         $this->img->ttf->SetUserFont($aNormal,$aBold,$aItalic,$aBoldIt);
     693        $this->img->ttf->SetUserFont($aNormal,$aBold,$aItalic,$aBoldIt);
    629694    }
    630695
    631696    function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    632         $this->img->ttf->SetUserFont1($aNormal,$aBold,$aItalic,$aBoldIt);
     697        $this->img->ttf->SetUserFont1($aNormal,$aBold,$aItalic,$aBoldIt);
    633698    }
    634699
    635700    function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    636         $this->img->ttf->SetUserFont2($aNormal,$aBold,$aItalic,$aBoldIt);
     701        $this->img->ttf->SetUserFont2($aNormal,$aBold,$aItalic,$aBoldIt);
    637702    }
    638703
    639704    function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    640         $this->img->ttf->SetUserFont3($aNormal,$aBold,$aItalic,$aBoldIt);
     705        $this->img->ttf->SetUserFont3($aNormal,$aBold,$aItalic,$aBoldIt);
    641706    }
    642707
    643708    // Set Image format and optional quality
    644709    function SetImgFormat($aFormat,$aQuality=75) {
    645         $this->img->SetImgFormat($aFormat,$aQuality);
     710        $this->img->SetImgFormat($aFormat,$aQuality);
    646711    }
    647712
    648713    // Should the grid be in front or back of the plot?
    649714    function SetGridDepth($aDepth) {
    650         $this->grid_depth=$aDepth;
     715        $this->grid_depth=$aDepth;
    651716    }
    652717
    653718    function SetIconDepth($aDepth) {
    654         $this->iIconDepth=$aDepth;
    655     }
    656        
     719        $this->iIconDepth=$aDepth;
     720    }
     721
    657722    // Specify graph angle 0-360 degrees.
    658723    function SetAngle($aAngle) {
    659         $this->img->SetAngle($aAngle);
     724        $this->img->SetAngle($aAngle);
    660725    }
    661726
    662727    function SetAlphaBlending($aFlg=true) {
    663         $this->img->SetAlphaBlending($aFlg);
     728        $this->img->SetAlphaBlending($aFlg);
    664729    }
    665730
    666731    // Shortcut to image margin
    667732    function SetMargin($lm,$rm,$tm,$bm) {
    668         $this->img->SetMargin($lm,$rm,$tm,$bm);
     733        $this->img->SetMargin($lm,$rm,$tm,$bm);
    669734    }
    670735
    671736    function SetY2OrderBack($aBack=true) {
    672         $this->y2orderback = $aBack;
    673     }
    674 
    675     // Rotate the graph 90 degrees and set the margin 
     737        $this->y2orderback = $aBack;
     738    }
     739
     740    // Rotate the graph 90 degrees and set the margin
    676741    // when we have done a 90 degree rotation
    677742    function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) {
    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        
     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
    694754    function SetClipping($aFlg=true) {
    695         $this->iDoClipping = $aFlg ;
     755        $this->iDoClipping = $aFlg ;
    696756    }
    697757
    698758    // Add a plot object to the graph
    699759    function Add($aPlot) {
    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;
     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        }
    719787    }
    720788
    721789    function AddTable($aTable) {
    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         }       
     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        }
    729798    }
    730799
    731800    function AddIcon($aIcon) {
    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         }       
     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        }
    739809    }
    740810
    741811    // Add plot to second Y-scale
    742812    function AddY2($aPlot) {
    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        
     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
    761842    // Add plot to the extra Y-axises
    762843    function AddY($aN,$aPlot) {
    763844
    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;
     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        }
    777868    }
    778869
    779870    // Add text object to the graph
    780871    function AddText($aTxt,$aToY2=false) {
    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        
     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
    801897    // Add a line object (class PlotLine) to the graph
    802898    function AddLine($aLine,$aToY2=false) {
    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         }
     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        }
    822927    }
    823928
    824929    // Add vertical or horizontal band
    825930    function AddBand($aBand,$aToY2=false) {
    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         }
     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;
    845961    }
    846962
    847963    function SetBackgroundGradient($aFrom='navy',$aTo='silver',$aGradType=2,$aStyle=BGRAD_FRAME) {
    848         $this->bkg_gradtype=$aGradType;
    849         $this->bkg_gradstyle=$aStyle;
    850         $this->bkg_gradfrom = $aFrom;
    851         $this->bkg_gradto = $aTo;
    852     } 
    853        
     964        $this->bkg_gradtype=$aGradType;
     965        $this->bkg_gradstyle=$aStyle;
     966        $this->bkg_gradfrom = $aFrom;
     967        $this->bkg_gradto = $aTo;
     968    }
     969
    854970    // Set a country flag in the background
    855971    function SetBackgroundCFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
    856         $this->background_cflag = $aName;
    857         $this->background_cflag_type = $aBgType;
    858         $this->background_cflag_mix = $aMix;
     972        $this->background_cflag = $aName;
     973        $this->background_cflag_type = $aBgType;
     974        $this->background_cflag_mix = $aMix;
    859975    }
    860976
    861977    // Alias for the above method
    862978    function SetBackgroundCountryFlag($aName,$aBgType=BGIMG_FILLPLOT,$aMix=100) {
    863         $this->background_cflag = $aName;
    864         $this->background_cflag_type = $aBgType;
    865         $this->background_cflag_mix = $aMix;
     979        $this->background_cflag = $aName;
     980        $this->background_cflag_type = $aBgType;
     981        $this->background_cflag_mix = $aMix;
    866982    }
    867983
    868984
    869985    // Specify a background image
    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;
     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;
    8961008    }
    8971009
    8981010    function SetBackgroundImageMix($aMix) {
    899         $this->background_image_mix = $aMix ;
    900     }
    901        
     1011        $this->background_image_mix = $aMix ;
     1012    }
     1013
    9021014    // Adjust background image position
    9031015    function SetBackgroundImagePos($aXpos,$aYpos) {
    904         $this->background_image_xpos = $aXpos ;
    905         $this->background_image_ypos = $aYpos ;
    906     }
    907        
     1016        $this->background_image_xpos = $aXpos ;
     1017        $this->background_image_ypos = $aYpos ;
     1018    }
     1019
    9081020    // Specify axis style (boxed or single)
    9091021    function SetAxisStyle($aStyle) {
    9101022        $this->iAxisStyle = $aStyle ;
    9111023    }
    912        
     1024
    9131025    // Set a frame around the plot area
    9141026    function SetBox($aDrawPlotFrame=true,$aPlotFrameColor=array(0,0,0),$aPlotFrameWeight=1) {
    915         $this->boxed = $aDrawPlotFrame;
    916         $this->box_weight = $aPlotFrameWeight;
    917         $this->box_color = $aPlotFrameColor;
    918     }
    919        
     1027        $this->boxed = $aDrawPlotFrame;
     1028        $this->box_weight = $aPlotFrameWeight;
     1029        $this->box_color = $aPlotFrameColor;
     1030    }
     1031
    9201032    // Specify color for the plotarea (not the margins)
    9211033    function SetColor($aColor) {
    922         $this->plotarea_color=$aColor;
    923     }
    924        
     1034        $this->plotarea_color=$aColor;
     1035    }
     1036
    9251037    // Specify color for the margins (all areas outside the plotarea)
    9261038    function SetMarginColor($aColor) {
    927         $this->margin_color=$aColor;
    928     }
    929        
     1039        $this->margin_color=$aColor;
     1040    }
     1041
    9301042    // Set a frame around the entire image
    9311043    function SetFrame($aDrawImgFrame=true,$aImgFrameColor=array(0,0,0),$aImgFrameWeight=1) {
    932         $this->doframe = $aDrawImgFrame;
    933         $this->frame_color = $aImgFrameColor;
    934         $this->frame_weight = $aImgFrameWeight;
     1044        $this->doframe = $aDrawImgFrame;
     1045        $this->frame_color = $aImgFrameColor;
     1046        $this->frame_weight = $aImgFrameWeight;
    9351047    }
    9361048
    9371049    function SetFrameBevel($aDepth=3,$aBorder=false,$aBorderColor='black',$aColor1='white@0.4',$aColor2='darkgray@0.4',$aFlg=true) {
    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 ;
     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 ;
    9461058    }
    9471059
    9481060    // Set the shadow around the whole image
    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;
     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;
    9551067    }
    9561068
     
    9581070    // you must also specify the tick distance with a call to Ticks::Set()
    9591071    function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) {
    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        
     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
    10011134    // Specify secondary Y scale
    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);                                                       
     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        }
    10221162    }
    10231163
    10241164    // Set the delta position (in pixels) between the multiple Y-axis
    10251165    function SetYDeltaDist($aDist) {
    1026         $this->iYAxisDeltaPos = $aDist;
     1166        $this->iYAxisDeltaPos = $aDist;
    10271167    }
    10281168
     
    10301170    function SetYScale($aN,$aAxisType="lin",$aYMin=1,$aYMax=1) {
    10311171
    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);
     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        }
    10461193    }
    10471194
    10481195    // Specify density of ticks when autoscaling 'normal', 'dense', 'sparse', 'verysparse'
    1049     // The dividing factor have been determined heuristically according to my aesthetic 
     1196    // The dividing factor have been determined heuristically according to my aesthetic
    10501197    // sense (or lack off) y.m.m.v !
    10511198    function SetTickDensity($aYDensity=TICKD_NORMAL,$aXDensity=TICKD_NORMAL) {
    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     
     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
    10901237    function GetCSIMareas() {
    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        
     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
    11461298    // Get a complete <MAP>..</MAP> tag for the final image map
    11471299    function GetHTMLImageMap($aMapName) {
    1148         $im = "<map name=\"$aMapName\" id=\"$aMapName\" >\n";
    1149         $im .= $this->GetCSIMareas();
    1150         $im .= "</map>";
    1151         return $im;
     1300        $im = "<map name=\"$aMapName\" id=\"$aMapName\" >\n";
     1301        $im .= $this->GetCSIMareas();
     1302        $im .= "</map>";
     1303        return $im;
    11521304    }
    11531305
    11541306    function CheckCSIMCache($aCacheName,$aTimeOut=60) {
    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;
     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;
    12001354    }
    12011355
    12021356    // Build the argument string to be used with the csim images
    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;
     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;
    12381394    }
    12391395
    12401396    function SetCSIMImgAlt($aAlt) {
    1241         $this->iCSIMImgAlt = $aAlt;
     1397        $this->iCSIMImgAlt = $aAlt;
    12421398    }
    12431399
    12441400    function StrokeCSIM($aScriptName='auto',$aCSIMName='',$aBorder=0) {
    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         }
     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";
    13121483    }
    13131484
    13141485    function GetTextsYMinMax($aY2=false) {
    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;
     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        }
    13391512    }
    13401513
    13411514    function GetTextsXMinMax($aY2=false) {
    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;
     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        }
    13661541    }
    13671542
    13681543    function GetXMinMax() {
    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);
     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);
    13991593    }
    14001594
    14011595    function AdjustMarginsForTitles() {
    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     }
     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
    14512008
    14522009    // Stroke the graph
    1453     // $aStrokeFileName If != "" the image will be written to this file and NOT
     2010    // $aStrokeFileName If != "" the image will be written to this file and NOT
    14542011    // streamed back to the browser
    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         }
     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        }
    20422283    }
    20432284
    20442285    function SetAxisLabelBackground($aType,$aXFColor='lightgray',$aXColor='black',$aYFColor='lightgray',$aYColor='black') {
    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     
     2286        $this->iAxisLblBgType = $aType;
     2287        $this->iXAxisLblBgFillColor = $aXFColor;
     2288        $this->iXAxisLblBgColor = $aXColor;
     2289        $this->iYAxisLblBgFillColor = $aYFColor;
     2290        $this->iYAxisLblBgColor = $aYColor;
     2291    }
    20542292
    20552293    function StrokeAxisLabelBackground() {
    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         }
     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        }
    21352374    }
    21362375
    21372376    function StrokeAxis($aStrokeLabels=true) {
    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         }
     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        }
    22202459    }
    22212460
     
    22232462    // Private helper function for backgound image
    22242463    static function LoadBkgImage($aImgFormat='',$aFile='',$aImgStr='') {
    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     }   
     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    }
    22782531
    22792532    function StrokeBackgroundGrad() {
    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         }
     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        }
    23092563    }
    23102564
    23112565    function StrokeFrameBackground() {
    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);             
     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);
    24022655    }
    24032656
     
    24052658    // Draw a frame around the image
    24062659    function StrokeFrame() {
    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         }
     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        }
    24442696    }
    24452697
    24462698    function FillMarginArea() {
    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);
     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);
    24662718    }
    24672719
    24682720    function FillPlotArea() {
    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    
     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
    24772729    // Stroke the plot area with either a solid color or a background image
    24782730    function StrokePlotArea() {
    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     }   
     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    }
    25022754
    25032755    function StrokeIcons() {
    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        
     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
    25102762    function StrokePlotBox() {
    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     }           
     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    }
    25242776
    25252777    function SetTitleBackgroundFillStyle($aStyle,$aColor1='black',$aColor2='white') {
    2526         $this->titlebkg_fillstyle = $aStyle;
    2527         $this->titlebkg_scolor1 = $aColor1;
    2528         $this->titlebkg_scolor2 = $aColor2;
     2778        $this->titlebkg_fillstyle = $aStyle;
     2779        $this->titlebkg_scolor1 = $aColor1;
     2780        $this->titlebkg_scolor2 = $aColor2;
    25292781    }
    25302782
    25312783    function SetTitleBackground($aBackColor='gray', $aStyle=TITLEBKG_STYLE1, $aFrameStyle=TITLEBKG_FRAME_NONE, $aFrameColor='black', $aFrameWeight=1, $aBevelHeight=3, $aEnable=true) {
    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 ;
     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 ;
    25392791    }
    25402792
     
    25422794    function StrokeTitles() {
    25432795
    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);
     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);
    27002954
    27012955    }
    27022956
    27032957    function StrokeTexts() {
    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         }
     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        }
    27162970
    27172971    }
    27182972
    27192973    function StrokeTables() {
    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         }
     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        }
    27262980    }
    27272981
    27282982    function DisplayClientSideaImageMapAreas() {
    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         }
     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        }
    27563010    }
    27573011
    27583012    // Text scale offset in world coordinates
    27593013    function SetTextScaleOff($aOff) {
    2760         $this->text_scale_off = $aOff;
    2761         $this->xscale->text_scale_off = $aOff;
     3014        $this->text_scale_off = $aOff;
     3015        $this->xscale->text_scale_off = $aOff;
    27623016    }
    27633017
    27643018    // Text width of bar to be centered in absolute pixels
    27653019    function SetTextScaleAbsCenterOff($aOff) {
    2766         $this->text_scale_abscenteroff = $aOff;
     3020        $this->text_scale_abscenteroff = $aOff;
    27673021    }
    27683022
    27693023    // Get Y min and max values for added lines
    27703024    function GetLinesYMinMax( $aLines ) {
    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 ;
     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 ;
    27853039    }
    27863040
    27873041    // Get X min and max values for added lines
    27883042    function GetLinesXMinMax( $aLines ) {
    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 ;
     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 ;
    28033057    }
    28043058
    28053059    // Get min and max values for all included plots
    28063060    function GetPlotsYMinMax($aPlots) {
    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);
     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        }
    28353162    }
    28363163
     
    28423169//===================================================
    28433170class LineProperty {
    2844     public $iWeight=1, $iColor="black",$iStyle="solid",$iShow=true;
    2845        
    2846 //---------------
    2847 // PUBLIC METHODS       
     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
    28483179    function SetColor($aColor) {
    2849         $this->iColor = $aColor;
    2850     }
    2851        
     3180        $this->iColor = $aColor;
     3181    }
     3182
    28523183    function SetWeight($aWeight) {
    2853         $this->iWeight = $aWeight;
    2854     }
    2855        
     3184        $this->iWeight = $aWeight;
     3185    }
     3186
    28563187    function SetStyle($aStyle) {
    2857         $this->iStyle = $aStyle;
    2858     }
    2859                
     3188        $this->iStyle = $aStyle;
     3189    }
     3190
    28603191    function Show($aShow=true) {
    2861         $this->iShow=$aShow;
    2862     }
    2863        
     3192        $this->iShow=$aShow;
     3193    }
     3194
    28643195    function Stroke($aImg,$aX1,$aY1,$aX2,$aY2) {
    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         }
     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        }
    28773208    }
    28783209}
    28793210
     3211//===================================================
     3212// CLASS GraphTabTitle
     3213// Description: Draw "tab" titles on top of graphs
     3214//===================================================
    28803215class GraphTabTitle extends Text{
    28813216    private $corner = 6 , $posx = 7, $posy = 4;
    28823217    private $fillcolor='lightyellow',$bordercolor='black';
    28833218    private $align = 'left', $width=TABTITLE_WIDTHFIT;
    2884     function GraphTabTitle() {
    2885         $this->t = '';
    2886         $this->font_style = FS_BOLD;
    2887         $this->hide = true;
    2888         $this->color = 'darkred';
     3219    function __construct() {
     3220        $this->t = '';
     3221        $this->font_style = FS_BOLD;
     3222        $this->hide = true;
     3223        $this->color = 'darkred';
    28893224    }
    28903225
    28913226    function SetColor($aTxtColor,$aFillColor='lightyellow',$aBorderColor='black') {
    2892         $this->color = $aTxtColor;
    2893         $this->fillcolor = $aFillColor;
    2894         $this->bordercolor = $aBorderColor;
     3227        $this->color = $aTxtColor;
     3228        $this->fillcolor = $aFillColor;
     3229        $this->bordercolor = $aBorderColor;
    28953230    }
    28963231
    28973232    function SetFillColor($aFillColor) {
    2898         $this->fillcolor = $aFillColor;
     3233        $this->fillcolor = $aFillColor;
    28993234    }
    29003235
    29013236    function SetTabAlign($aAlign) {
    2902         $this->align = $aAlign;
    2903     }
    2904    
     3237        $this->align = $aAlign;
     3238    }
     3239
    29053240    function SetWidth($aWidth) {
    2906         $this->width = $aWidth ;
     3241        $this->width = $aWidth ;
    29073242    }
    29083243
    29093244    function Set($t) {
    2910         $this->t = $t;
    2911         $this->hide = false;
     3245        $this->t = $t;
     3246        $this->hide = false;
    29123247    }
    29133248
    29143249    function SetCorner($aD) {
    2915         $this->corner = $aD ;
     3250        $this->corner = $aD ;
    29163251    }
    29173252
    29183253    function Stroke($aImg,$aDummy1=null,$aDummy2=null) {
    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');
     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');
    29963333    }
    29973334
     
    30033340//===================================================
    30043341class SuperScriptText extends Text {
    3005     private $iSuper="";
    3006     private $sfont_family="",$sfont_style="",$sfont_size=8;
     3342    private $iSuper='';
     3343    private $sfont_family='',$sfont_style='',$sfont_size=8;
    30073344    private $iSuperMargin=2,$iVertOverlap=4,$iSuperScale=0.65;
    30083345    private $iSDir=0;
    30093346    private $iSimple=false;
    30103347
    3011     function SuperScriptText($aTxt="",$aSuper="",$aXAbsPos=0,$aYAbsPos=0) {
    3012         parent::Text($aTxt,$aXAbsPos,$aYAbsPos);
    3013         $this->iSuper = $aSuper;
     3348    function __construct($aTxt='',$aSuper='',$aXAbsPos=0,$aYAbsPos=0) {
     3349        parent::__construct($aTxt,$aXAbsPos,$aYAbsPos);
     3350        $this->iSuper = $aSuper;
    30143351    }
    30153352
    30163353    function FromReal($aVal,$aPrecision=2) {
    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;
     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;
    30433383    }
    30443384
    30453385    function SetSuperFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=8) {
    3046         $this->sfont_family = $aFontFam;
    3047         $this->sfont_style = $aFontStyle;
    3048         $this->sfont_size = $aFontSize;
     3386        $this->sfont_family = $aFontFam;
     3387        $this->sfont_style = $aFontStyle;
     3388        $this->sfont_size = $aFontSize;
    30493389    }
    30503390
    30513391    // Total width of text
    30523392    function GetWidth($aImg) {
    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        
     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
    30613401    // Hight of font (approximate the height of the text)
    30623402    function GetFontHeight($aImg) {
    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;
     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;
    30683408    }
    30693409
    30703410    // Hight of text
    30713411    function GetTextHeight($aImg) {
    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;
     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;
    30773417    }
    30783418
    30793419    function Stroke($aImg,$ax=-1,$ay=-1) {
    3080        
     3420
    30813421        // To position the super script correctly we need different
    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();     
     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();
    31723513    }
    31733514}
     
    31813522    protected $img;
    31823523    protected $scale;
    3183     protected $grid_color='#DDDDDD',$grid_mincolor='#DDDDDD';
    3184     protected $type="solid";
    3185     protected $show=false, $showMinor=false,$weight=1;
     3524    protected $majorcolor='#CCCCCC',$minorcolor='#DDDDDD';
     3525    protected $majortype='solid',$minortype='solid';
     3526    protected $show=false, $showMinor=false,$majorweight=1,$minorweight=1;
    31863527    protected $fill=false,$fillcolor=array('#EFEFEF','#BBCCFF');
    3187 //---------------
    3188 // CONSTRUCTOR
    3189     function Grid($aAxis) {
    3190         $this->scale = $aAxis->scale;
    3191         $this->img = $aAxis->img;
    3192     }
    3193 //---------------
    3194 // PUBLIC METHODS
     3528
     3529    function __construct($aAxis) {
     3530        $this->scale = $aAxis->scale;
     3531        $this->img = $aAxis->img;
     3532    }
     3533
    31953534    function SetColor($aMajColor,$aMinColor=false) {
    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        
     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
    32063547    // Specify if grid should be dashed, dotted or solid
    3207     function SetLineStyle($aType) {
    3208         $this->type = $aType;
    3209     }
    3210        
     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
    32113557    // Decide if both major and minor grid should be displayed
    32123558    function Show($aShowMajor=true,$aShowMinor=false) {
    3213         $this->show=$aShowMajor;
    3214         $this->showMinor=$aShowMinor;
    3215     }
    3216    
     3559        $this->show=$aShowMajor;
     3560        $this->showMinor=$aShowMinor;
     3561    }
     3562
    32173563    function SetFill($aFlg=true,$aColor1='lightgray',$aColor2='lightblue') {
    3218         $this->fill = $aFlg;
    3219         $this->fillcolor = array( $aColor1, $aColor2 );
    3220     }
    3221        
     3564        $this->fill = $aFlg;
     3565        $this->fillcolor = array( $aColor1, $aColor2 );
     3566    }
     3567
    32223568    // Display the grid
    32233569    function Stroke() {
    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     
     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
    32393581    // Draw the grid
    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;
     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;
    33213658    }
    33223659} // Class
     
    33283665// several occasion must know wheter it's an X or Y axis.
    33293666// This was a design decision to make the code easier to
    3330 // follow. 
     3667// follow.
    33313668//===================================================
    33323669class AxisPrototype {
    3333     public $scale=null; 
     3670    public $scale=null;
    33343671    public $img=null;
    33353672    public $hide=false,$hide_labels=false;
    33363673    public $title=null;
    3337     public $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12,$label_angle=0;
     3674    public $font_family=FF_DEFAULT,$font_style=FS_NORMAL,$font_size=8,$label_angle=0;
    33383675    public $tick_step=1;
    33393676    public $pos = false;
     
    33483685    protected $labelPos=0;   // Which side of the axis should the labels be?
    33493686    protected $title_adjust,$title_margin,$title_side=SIDE_LEFT;
    3350     protected $tick_label_margin=7;
     3687    protected $tick_label_margin=5;
    33513688    protected $label_halign = '',$label_valign = '', $label_para_align='left';
    33523689    protected $hide_line=false;
    33533690    protected $iDeltaAbsPos=0;
    33543691
    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        
     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
    33823715    function SetLabelFormat($aFormStr) {
    3383         $this->scale->ticks->SetLabelFormat($aFormStr);
     3716        $this->scale->ticks->SetLabelFormat($aFormStr);
    33843717    }
    33853718
    33863719    function SetLabelFormatString($aFormStr,$aDate=false) {
    3387         $this->scale->ticks->SetLabelFormat($aFormStr,$aDate);
    3388     }
    3389        
     3720        $this->scale->ticks->SetLabelFormat($aFormStr,$aDate);
     3721    }
     3722
    33903723    function SetLabelFormatCallback($aFuncName) {
    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     }           
     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    }
    33993732
    34003733    // Don't display the first label
    34013734    function HideFirstTickLabel($aShow=false) {
    3402         $this->show_first_label=$aShow;
     3735        $this->show_first_label=$aShow;
    34033736    }
    34043737
    34053738    function HideLastTickLabel($aShow=false) {
    3406         $this->show_last_label=$aShow;
     3739        $this->show_last_label=$aShow;
    34073740    }
    34083741
    34093742    // Manually specify the major and (optional) minor tick position and labels
    34103743    function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) {
    3411         $this->scale->ticks->SetTickPositions($aMajPos,$aMinPos,$aLabels);
     3744        $this->scale->ticks->SetTickPositions($aMajPos,$aMinPos,$aLabels);
    34123745    }
    34133746
    34143747    // Manually specify major tick positions and optional labels
    34153748    function SetMajTickPositions($aMajPos,$aLabels=NULL) {
    3416         $this->scale->ticks->SetTickPositions($aMajPos,NULL,$aLabels);
     3749        $this->scale->ticks->SetTickPositions($aMajPos,NULL,$aLabels);
    34173750    }
    34183751
    34193752    // Hide minor or major tick marks
    34203753    function HideTicks($aHideMinor=true,$aHideMajor=true) {
    3421         $this->scale->ticks->SupressMinorTickMarks($aHideMinor);
    3422         $this->scale->ticks->SupressTickMarks($aHideMajor);
     3754        $this->scale->ticks->SupressMinorTickMarks($aHideMinor);
     3755        $this->scale->ticks->SupressTickMarks($aHideMajor);
    34233756    }
    34243757
    34253758    // Hide zero label
    34263759    function HideZeroLabel($aFlag=true) {
    3427         $this->scale->ticks->SupressZeroLabel();
    3428     }
    3429        
     3760        $this->scale->ticks->SupressZeroLabel();
     3761    }
     3762
    34303763    function HideFirstLastLabel() {
    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        
     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
    34423775    // Hide the axis
    34433776    function Hide($aHide=true) {
    3444         $this->hide=$aHide;
     3777        $this->hide=$aHide;
    34453778    }
    34463779
    34473780    // Hide the actual axis-line, but still print the labels
    34483781    function HideLine($aHide=true) {
    3449         $this->hide_line = $aHide;
     3782        $this->hide_line = $aHide;
    34503783    }
    34513784
    34523785    function HideLabels($aHide=true) {
    3453         $this->hide_labels = $aHide;
    3454     }
    3455    
     3786        $this->hide_labels = $aHide;
     3787    }
    34563788
    34573789    // Weight of axis
    34583790    function SetWeight($aWeight) {
    3459         $this->weight = $aWeight;
     3791        $this->weight = $aWeight;
    34603792    }
    34613793
    34623794    // Axis color
    34633795    function SetColor($aColor,$aLabelColor=false) {
    3464         $this->color = $aColor;
    3465         if( !$aLabelColor ) $this->label_color = $aColor;
    3466         else $this->label_color = $aLabelColor;
    3467     }
    3468        
     3796        $this->color = $aColor;
     3797        if( !$aLabelColor ) $this->label_color = $aColor;
     3798        else $this->label_color = $aLabelColor;
     3799    }
     3800
    34693801    // Title on axis
    3470     function SetTitle($aTitle,$aAdjustAlign="high") {
    3471         $this->title->Set($aTitle);
    3472         $this->title_adjust=$aAdjustAlign;
    3473     }
    3474        
     3802    function SetTitle($aTitle,$aAdjustAlign='high') {
     3803        $this->title->Set($aTitle);
     3804        $this->title_adjust=$aAdjustAlign;
     3805    }
     3806
    34753807    // Specify distance from the axis
    34763808    function SetTitleMargin($aMargin) {
    3477         $this->title_margin=$aMargin;
    3478     }
    3479        
     3809        $this->title_margin=$aMargin;
     3810    }
     3811
    34803812    // Which side of the axis should the axis title be?
    34813813    function SetTitleSide($aSideOfAxis) {
    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    
     3814        $this->title_side = $aSideOfAxis;
     3815    }
     3816
    34933817    function SetTickSide($aDir) {
    3494         $this->scale->ticks->SetSide($aDir);
    3495     }
    3496        
     3818        $this->scale->ticks->SetSide($aDir);
     3819    }
     3820
     3821    function SetTickSize($aMajSize,$aMinSize=3) {
     3822        $this->scale->ticks->SetSize($aMajSize,$aMinSize=3);
     3823    }
     3824
    34973825    // Specify text labels for the ticks. One label for each data point
    34983826    function SetTickLabels($aLabelArray,$aLabelColorArray=null) {
    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;
     3827        $this->ticks_label = $aLabelArray;
     3828        $this->ticks_label_colors = $aLabelColorArray;
    35083829    }
    35093830
    35103831    function SetLabelMargin($aMargin) {
    3511         $this->tick_label_margin=$aMargin;
    3512     }
    3513        
     3832        $this->tick_label_margin=$aMargin;
     3833    }
     3834
    35143835    // Specify that every $step of the ticks should be displayed starting
    35153836    // 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       
    35233837    function SetTextTickInterval($aStep,$aStart=0) {
    3524         $this->scale->ticks->SetTextLabelStart($aStart);
    3525         $this->tick_step=$aStep;
    3526     }
    3527          
    3528     // Specify that every $step tick mark should have a label 
     3838        $this->scale->ticks->SetTextLabelStart($aStart);
     3839        $this->tick_step=$aStep;
     3840    }
     3841
     3842    // Specify that every $step tick mark should have a label
    35293843    // should be displayed starting
    35303844    function SetTextLabelInterval($aStep) {
    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    
     3845        if( $aStep < 1 ) {
     3846            JpGraphError::RaiseL(25058);//(" Text label interval must be specified >= 1.");
     3847        }
     3848        $this->label_step=$aStep;
     3849    }
     3850
    35443851    function SetLabelSide($aSidePos) {
    3545         $this->labelPos=$aSidePos;
     3852        $this->labelPos=$aSidePos;
    35463853    }
    35473854
    35483855    // Set the font
    35493856    function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) {
    3550         $this->font_family = $aFamily;
    3551         $this->font_style = $aStyle;
    3552         $this->font_size = $aSize;
     3857        $this->font_family = $aFamily;
     3858        $this->font_style = $aStyle;
     3859        $this->font_size = $aSize;
    35533860    }
    35543861
    35553862    // Position for axis line on the "other" scale
    35563863    function SetPos($aPosOnOtherScale) {
    3557         $this->pos=$aPosOnOtherScale;
    3558     }
    3559 
    3560     // Set the position of the axis to be X-pixels delta to the right 
     3864        $this->pos=$aPosOnOtherScale;
     3865    }
     3866
     3867    // Set the position of the axis to be X-pixels delta to the right
    35613868    // of the max X-position (used to position the multiple Y-axis)
    35623869    function SetPosAbsDelta($aDelta) {
    3563       $this->iDeltaAbsPos=$aDelta;
    3564     }
    3565        
     3870        $this->iDeltaAbsPos=$aDelta;
     3871    }
     3872
    35663873    // Specify the angle for the tick labels
    35673874    function SetLabelAngle($aAngle) {
    3568         $this->label_angle = $aAngle;
    3569     }   
     3875        $this->label_angle = $aAngle;
     3876    }
    35703877
    35713878} // Class
     
    35783885// several occasion must know wheter it's an X or Y axis.
    35793886// This was a design decision to make the code easier to
    3580 // follow. 
     3887// follow.
    35813888//===================================================
    35823889class Axis extends AxisPrototype {
    35833890
    3584     function Axis($img,$aScale,$color=array(0,0,0)) {
    3585         parent::Axis($img,$aScale,$color);
    3586     }
    3587        
     3891    function __construct($img,$aScale,$color='black') {
     3892        parent::__construct($img,$aScale,$color);
     3893    }
     3894
    35883895    // Stroke the axis.
    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     
     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
    36774008    // Draw all the tick labels on major tick marks
    36784009    function StrokeLabels($aPos,$aMinor=false,$aAbsLabel=false) {
    36794010
    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     }                       
     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    }
    37924154
    37934155}
     
    38054167    public $direction=1; // Should ticks be in(=1) the plot area or outside (=-1)
    38064168    public $supress_last=false,$supress_tickmarks=false,$supress_minor_tickmarks=false;
    3807     public $maj_ticks_pos = array(), $maj_ticklabels_pos = array(), 
    3808            $ticks_pos = array(), $maj_ticks_label = array();
     4169    public $maj_ticks_pos = array(), $maj_ticklabels_pos = array(),
     4170           $ticks_pos = array(), $maj_ticks_label = array();
    38094171    public $precision;
    38104172
     
    38134175    protected $is_set=false;
    38144176    protected $supress_zerolabel=false,$supress_first=false;
    3815     protected $mincolor="",$majcolor="";
     4177    protected $mincolor='',$majcolor='';
    38164178    protected $weight=1;
    38174179    protected $label_usedateformat=FALSE;
    38184180
    3819 //---------------
    3820 // CONSTRUCTOR
    3821     function Ticks($aScale) {
    3822         $this->scale=$aScale;
    3823         $this->precision = -1;
    3824     }
    3825 
    3826 //---------------
    3827 // PUBLIC METHODS       
     4181    function __construct($aScale) {
     4182        $this->scale=$aScale;
     4183        $this->precision = -1;
     4184    }
     4185
    38284186    // Set format string for automatic labels
    38294187    function SetLabelFormat($aFormatString,$aDate=FALSE) {
    3830         $this->label_formatstr=$aFormatString;
    3831         $this->label_usedateformat=$aDate;
    3832     }
    3833        
     4188        $this->label_formatstr=$aFormatString;
     4189        $this->label_usedateformat=$aDate;
     4190    }
     4191
    38344192    function SetLabelDateFormat($aFormatString) {
    3835         $this->label_dateformatstr=$aFormatString;
    3836     }
    3837        
     4193        $this->label_dateformatstr=$aFormatString;
     4194    }
     4195
    38384196    function SetFormatCallback($aCallbackFuncName) {
    3839         $this->label_formfunc = $aCallbackFuncName;
    3840     }
    3841        
     4197        $this->label_formfunc = $aCallbackFuncName;
     4198    }
     4199
    38424200    // Don't display the first zero label
    38434201    function SupressZeroLabel($aFlag=true) {
    3844         $this->supress_zerolabel=$aFlag;
    3845     }
    3846        
     4202        $this->supress_zerolabel=$aFlag;
     4203    }
     4204
    38474205    // Don't display minor tick marks
    38484206    function SupressMinorTickMarks($aHide=true) {
    3849         $this->supress_minor_tickmarks=$aHide;
    3850     }
    3851        
     4207        $this->supress_minor_tickmarks=$aHide;
     4208    }
     4209
    38524210    // Don't display major tick marks
    38534211    function SupressTickMarks($aHide=true) {
    3854         $this->supress_tickmarks=$aHide;
    3855     }
    3856        
     4212        $this->supress_tickmarks=$aHide;
     4213    }
     4214
    38574215    // Hide the first tick mark
    38584216    function SupressFirst($aHide=true) {
    3859         $this->supress_first=$aHide;
    3860     }
    3861        
     4217        $this->supress_first=$aHide;
     4218    }
     4219
    38624220    // Hide the last tick mark
    38634221    function SupressLast($aHide=true) {
    3864         $this->supress_last=$aHide;
     4222        $this->supress_last=$aHide;
    38654223    }
    38664224
    38674225    // Size (in pixels) of minor tick marks
    38684226    function GetMinTickAbsSize() {
    3869         return $this->minor_abs_size;
    3870     }
    3871        
     4227        return $this->minor_abs_size;
     4228    }
     4229
    38724230    // Size (in pixels) of major tick marks
    38734231    function GetMajTickAbsSize() {
    3874         return $this->major_abs_size;           
    3875     }
    3876        
     4232        return $this->major_abs_size;
     4233    }
     4234
    38774235    function SetSize($aMajSize,$aMinSize=3) {
    3878         $this->major_abs_size = $aMajSize;             
    3879         $this->minor_abs_size = $aMinSize;             
     4236        $this->major_abs_size = $aMajSize;
     4237        $this->minor_abs_size = $aMinSize;
    38804238    }
    38814239
    38824240    // Have the ticks been specified
    38834241    function IsSpecified() {
    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;
     4242        return $this->is_set;
    38934243    }
    38944244
    38954245    function SetSide($aSide) {
    3896         $this->direction=$aSide;
    3897     }
    3898        
     4246        $this->direction=$aSide;
     4247    }
     4248
    38994249    // Which side of the axis should the ticks be on
    39004250    function SetDirection($aSide=SIDE_RIGHT) {
    3901         $this->direction=$aSide;
    3902     }
    3903        
     4251        $this->direction=$aSide;
     4252    }
     4253
    39044254    // Set colors for major and minor tick marks
    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        
     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
    39194271    function SetWeight($aWeight) {
    3920         $this->weight=$aWeight;
    3921     }
    3922        
     4272        $this->weight=$aWeight;
     4273    }
     4274
    39234275} // Class
    39244276
     
    39364288    private $iAdjustForDST = false; // If a date falls within the DST period add one hour to the diaplyed time
    39374289
    3938 //---------------
    3939 // CONSTRUCTOR
    3940     function LinearTicks() {
    3941         $this->precision = -1;
    3942     }
    3943 
    3944 //---------------
    3945 // PUBLIC METHODS       
    3946        
    3947        
     4290    function __construct() {
     4291        $this->precision = -1;
     4292    }
     4293
    39484294    // Return major step size in world coordinates
    39494295    function GetMajor() {
    3950         return $this->major_step;
    3951     }
    3952        
     4296        return $this->major_step;
     4297    }
     4298
    39534299    // Return minor step size in world coordinates
    39544300    function GetMinor() {
    3955         return $this->minor_step;
    3956     }
    3957        
     4301        return $this->minor_step;
     4302    }
     4303
    39584304    // Set Minor and Major ticks (in world coordinates)
    39594305    function Set($aMajStep,$aMinStep=false) {
    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;
     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;
    39714318    }
    39724319
    39734320    function SetMajTickPositions($aMajPos,$aLabels=NULL) {
    3974         $this->SetTickPositions($aMajPos,NULL,$aLabels);
     4321        $this->SetTickPositions($aMajPos,NULL,$aLabels);
    39754322    }
    39764323
    39774324    function SetTickPositions($aMajPos,$aMinPos=NULL,$aLabels=NULL) {
    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         }
     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        }
    40464393    }
    40474394
    40484395    function _doAutoTickPos($aScale) {
    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         }       
     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        }
    41254476    }
    41264477
    41274478    function AdjustForDST($aFlg=true) {
    4128         $this->iAdjustForDST = $aFlg;
     4479        $this->iAdjustForDST = $aFlg;
    41294480    }
    41304481
     
    41324483    function _doLabelFormat($aVal,$aIdx,$aNbrTicks) {
    41334484
    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;
     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;
    41884551    }
    41894552
    41904553    // Stroke ticks on either X or Y axis
    41914554    function _StrokeTicks($aImg,$aScale,$aPos) {
    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        
     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
    42424613    }
    42434614
    42444615    // Draw linear ticks
    42454616    function Stroke($aImg,$aScale,$aPos) {
    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
     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
    42554628    // Spoecify the offset of the displayed tick mark with the tick "space"
    4256     // Legal values for $o is [0,1] used to adjust where the tick marks and label 
     4629    // Legal values for $o is [0,1] used to adjust where the tick marks and label
    42574630    // should be positioned within the major tick-size
    42584631    // $lo specifies the label offset and $to specifies the tick offset
     
    42604633    // tick but have the labels displayed halfway under the bars.
    42614634    function SetXLabelOffset($aLabelOff,$aTickOff=-1) {
    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
     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        }
    42694646    }
    42704647
    42714648    // Which tick label should we start with?
    42724649    function SetTextLabelStart($aTextLabelOff) {
    4273         $this->text_label_start=$aTextLabelOff;
    4274     }
    4275        
     4650        $this->text_label_start=$aTextLabelOff;
     4651    }
     4652
    42764653} // Class
    42774654
    42784655//===================================================
    42794656// CLASS LinearScale
    4280 // Description: Handle linear scaling between screen and world 
     4657// Description: Handle linear scaling between screen and world
    42814658//===================================================
    42824659class LinearScale {
     
    42974674    public $auto_ticks=false; // When using manual scale should the ticks be automatically set?
    42984675    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
    43004676    public $intscale=false; // Restrict autoscale to integers
    43014677    protected $autoscale_min=false; // Forced minimum value, auto determine max
    43024678    protected $autoscale_max=false; // Forced maximum value, auto determine min
    43034679    private $gracetop=0,$gracebottom=0;
    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       
     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
    43184693    // Check if scale is set or if we should autoscale
    43194694    // We should do this is either scale or ticks has not been set
    43204695    function IsSpecified() {
    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. 
     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.
    43284703    // Usefull if you want a fix minimum (like 0) but have an
    43294704    // automatic maximum
    43304705    function SetAutoMin($aMin) {
    4331         $this->autoscale_min=$aMin;
    4332     }
    4333 
    4334     // Set the minimum data value when the autoscaling is used. 
     4706        $this->autoscale_min=$aMin;
     4707    }
     4708
     4709    // Set the minimum data value when the autoscaling is used.
    43354710    // Usefull if you want a fix minimum (like 0) but have an
    43364711    // automatic maximum
    43374712    function SetAutoMax($aMax) {
    4338         $this->autoscale_max=$aMax;
     4713        $this->autoscale_max=$aMax;
    43394714    }
    43404715
     
    43424717    // still be set automatically?
    43434718    function SetAutoTicks($aFlag=true) {
    4344         $this->auto_ticks = $aFlag;
     4719        $this->auto_ticks = $aFlag;
    43454720    }
    43464721
    43474722    // Specify scale "grace" value (top and bottom)
    43484723    function SetGrace($aGraceTop,$aGraceBottom=0) {
    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        
     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
    43554731    // Get the minimum value in the scale
    43564732    function GetMinVal() {
    4357         return $this->scale[0];
    4358     }
    4359        
     4733        return $this->scale[0];
     4734    }
     4735
    43604736    // get maximum value for scale
    43614737    function GetMaxVal() {
    4362         return $this->scale[1];
    4363     }
    4364                
    4365     // Specify a new min/max value for sclae   
     4738        return $this->scale[1];
     4739    }
     4740
     4741    // Specify a new min/max value for sclae
    43664742    function Update($aImg,$aMin,$aMax) {
    4367         $this->scale=array($aMin,$aMax);               
    4368         $this->world_size=$aMax-$aMin;         
    4369         $this->InitConstants($aImg);                                   
    4370     }
    4371        
     4743        $this->scale=array($aMin,$aMax);
     4744        $this->world_size=$aMax-$aMin;
     4745        $this->InitConstants($aImg);
     4746    }
     4747
    43724748    // Translate between world and screen
    43734749    function Translate($aCoord) {
    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        
     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
    43844761    // Relative translate (don't include offset) usefull when we just want
    43854762    // to know the relative position (in pixels) on the axis
    43864763    function RelTranslate($aCoord) {
    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        
     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
    43974775    // Restrict autoscaling to only use integers
    43984776    function SetIntScale($aIntScale=true) {
    4399         $this->intscale=$aIntScale;
    4400     }
    4401        
     4777        $this->intscale=$aIntScale;
     4778    }
     4779
    44024780    // Calculate an integer autoscale
    44034781    function IntAutoScale($img,$min,$max,$maxsteps,$majend=true) {
    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        
     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
    45254895    // Calculate autoscale. Used if user hasn't given a scale and ticks
    45264896    // $maxsteps is the maximum number of major tickmarks allowed.
    45274897    function AutoScale($img,$min,$max,$maxsteps,$majend=true) {
    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     
     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
    46315002
    46325003    // This method recalculates all constants that are depending on the
     
    46355006    // that image. Should really be installed as an observer of that image.
    46365007    function InitConstants($img) {
    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        
     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
    46555028    // Initialize the conversion constants for this scale
    46565029    // This tries to pre-calculate as much as possible to speed up the
    46575030    // actual conversion (with Translate()) later on
    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                     
     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
    46615034    function SetConstants($aStart,$aLen) {
    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        
     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
    46805052    // Calculate number of ticks steps with a specific division
    46815053    // $a is the divisor of 10**x to generate the first maj tick intervall
     
    46845056    // $a=2, $b=5 give major ticks with multiple of 5:s ...,0.5,5,50,...
    46855057    // We return a vector of
    4686     //  [$numsteps,$adjmin,$adjmax,$minstep,$majstep]
     5058    //  [$numsteps,$adjmin,$adjmax,$minstep,$majstep]
    46875059    // If $majend==true then the first and last marks on the axis will be major
    46885060    // labeled tick marks otherwise it will be adjusted to the closest min tick mark
    46895061    function CalcTicks($maxsteps,$min,$max,$a,$b,$majend=true) {
    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);
     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);
    47265101    }
    47275102
    47285103    function CalcTicksFreeze($maxsteps,$min,$max,$a,$b) {
    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        
     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
    47515128    function IntCalcTicks($maxsteps,$min,$max,$a,$majend=true) {
    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);               
     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);
    47895173    }
    47905174
    47915175
    47925176    function IntCalcTicksFreeze($maxsteps,$min,$max,$a) {
    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        
     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
    48195205    // Determine the minimum of three values witha  weight for last value
    48205206    function MatchMin3($a,$b,$c,$weight) {
    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
     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;
    48305233    }
    48315234} // Class
     
    48395242    public $margin=5;
    48405243    public $show=false;
    4841     public $valign="",$halign="center";
    4842     public $format="%.1f",$negformat="";
    4843     private $ff=FF_FONT1,$fs=FS_NORMAL,$fsize=10;
     5244    public $valign='',$halign='center';
     5245    public $format='%.1f',$negformat='';
     5246    private $ff=FF_DEFAULT,$fs=FS_NORMAL,$fsize=8;
    48445247    private $iFormCallback='';
    48455248    private $angle=0;
    4846     private $color="navy",$negcolor="";
     5249    private $color='navy',$negcolor='';
    48475250    private $iHideZero=false;
     5251    public $txt=null;
     5252
     5253    function __construct() {
     5254                $this->txt = new Text();
     5255    }
    48485256
    48495257    function Show($aFlag=true) {
    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;
     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;
    48625270    }
    48635271
    48645272    function ApplyFont($aImg) {
    4865         $aImg->SetFont($this->ff,$this->fs,$this->fsize);
     5273        $aImg->SetFont($this->ff,$this->fs,$this->fsize);
    48665274    }
    48675275
    48685276    function SetMargin($aMargin) {
    4869         $this->margin = $aMargin;
     5277        $this->margin = $aMargin;
    48705278    }
    48715279
    48725280    function SetAngle($aAngle) {
    4873         $this->angle = $aAngle;
     5281        $this->angle = $aAngle;
    48745282    }
    48755283
    48765284    function SetAlign($aHAlign,$aVAlign='') {
    4877         $this->halign = $aHAlign;
    4878         $this->valign = $aVAlign;
    4879     }
    4880 
    4881     function SetFormat($aFormat,$aNegFormat="") {
    4882         $this->format= $aFormat;
    4883         $this->negformat= $aNegFormat;
     5285        $this->halign = $aHAlign;
     5286        $this->valign = $aVAlign;
     5287    }
     5288
     5289    function SetFormat($aFormat,$aNegFormat='') {
     5290        $this->format= $aFormat;
     5291        $this->negformat= $aNegFormat;
    48845292    }
    48855293
    48865294    function SetFormatCallback($aFunc) {
    4887         $this->iFormCallback = $aFunc;
     5295        $this->iFormCallback = $aFunc;
    48885296    }
    48895297
    48905298    function HideZero($aFlag=true) {
    4891         $this->iHideZero=$aFlag;
     5299        $this->iHideZero=$aFlag;
    48925300    }
    48935301
    48945302    function Stroke($img,$aVal,$x,$y) {
    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         }
     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        }
    49465368    }
    49475369}
     
    49565378    public $legend='';
    49575379    public $coords=array();
    4958     public $color="black";
     5380    public $color='black';
    49595381    public $hidelegend=false;
    49605382    public $line_weight=1;
    49615383    public $csimtargets=array(),$csimwintargets=array(); // Array of targets for CSIM
    4962     public $csimareas="";                       // Resultant CSIM area tags     
    4963     public $csimalts=null;                      // ALT:s for corresponding target
     5384    public $csimareas='';   // Resultant CSIM area tags
     5385    public $csimalts=null;   // ALT:s for corresponding target
    49645386    public $legendcsimtarget='',$legendcsimwintarget='';
    49655387    public $legendcsimalt='';
    4966     protected $weight=1;       
     5388    protected $weight=1;
    49675389    protected $center=false;
    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       
     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    }
    49895418
    49905419    // Stroke the plot
     
    49925421    // the subclasses
    49935422    function Stroke($aImg,$aXScale,$aYScale) {
    4994         JpGraphError::RaiseL(25122);//("JpGraph: Stroke() must be implemented by concrete subclass to class Plot");
     5423        JpGraphError::RaiseL(25122);//("JpGraph: Stroke() must be implemented by concrete subclass to class Plot");
    49955424    }
    49965425
    49975426    function HideLegend($f=true) {
    4998         $this->hidelegend = $f;
     5427        $this->hidelegend = $f;
    49995428    }
    50005429
    50015430    function DoLegend($graph) {
    5002         if( !$this->hidelegend )
    5003             $this->Legend($graph);
     5431        if( !$this->hidelegend )
     5432        $this->Legend($graph);
    50045433    }
    50055434
    50065435    function StrokeDataValue($img,$aVal,$x,$y) {
    5007         $this->value->Stroke($img,$aVal,$x,$y);
    5008     }
    5009        
    5010     // Set href targets for CSIM       
     5436        $this->value->Stroke($img,$aVal,$x,$y);
     5437    }
     5438
     5439    // Set href targets for CSIM
    50115440    function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') {
    5012         $this->csimtargets=$aTargets;
    5013         $this->csimwintargets=$aWinTargets;
    5014         $this->csimalts=$aAlts;         
    5015     }
    5016        
     5441        $this->csimtargets=$aTargets;
     5442        $this->csimwintargets=$aWinTargets;
     5443        $this->csimalts=$aAlts;
     5444    }
     5445
    50175446    // Get all created areas
    50185447    function GetCSIMareas() {
    5019         return $this->csimareas;
    5020     }   
    5021        
     5448        return $this->csimareas;
     5449    }
     5450
    50225451    // "Virtual" function which gets called before any scale
    50235452    // or axis are stroked used to do any plot specific adjustment
    50245453    function PreStrokeAdjust($aGraph) {
    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        
     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
    50305466    // Get minimum values in plot
    50315467    function Min() {
    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        
     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
    50645500    // Get maximum value in plot
    50655501    function Max() {
    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        
     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
    51015535    function SetColor($aColor) {
    5102         $this->color=$aColor;
    5103     }
    5104        
     5536        $this->color=$aColor;
     5537    }
     5538
    51055539    function SetLegend($aLegend,$aCSIM='',$aCSIMAlt='',$aCSIMWinTarget='') {
    5106         $this->legend = $aLegend;
    5107         $this->legendcsimtarget = $aCSIM;
    5108         $this->legendcsimwintarget = $aCSIMWinTarget;
    5109         $this->legendcsimalt = $aCSIMAlt;
     5540        $this->legend = $aLegend;
     5541        $this->legendcsimtarget = $aCSIM;
     5542        $this->legendcsimwintarget = $aCSIMWinTarget;
     5543        $this->legendcsimalt = $aCSIMAlt;
    51105544    }
    51115545
    51125546    function SetWeight($aWeight) {
    5113         $this->weight=$aWeight;
    5114     }
    5115                
     5547        $this->weight=$aWeight;
     5548    }
     5549
    51165550    function SetLineWeight($aWeight=1) {
    5117         $this->line_weight=$aWeight;
    5118     }
    5119        
     5551        $this->line_weight=$aWeight;
     5552    }
     5553
    51205554    function SetCenter($aCenter=true) {
    5121         $this->center = $aCenter;
    5122     }
    5123        
     5555        $this->center = $aCenter;
     5556    }
     5557
    51245558    // This method gets called by Graph class to plot anything that should go
    51255559    // into the margin after the margin color has been set.
    51265560    function StrokeMargin($aImg) {
    5127         return true;
     5561        return true;
    51285562    }
    51295563
    51305564    // Framework function the chance for each plot class to set a legend
    51315565    function Legend($aGraph) {
    5132         if( $this->legend != "" )
    5133             $aGraph->legend->Add($this->legend,$this->color,"",0,$this->legendcsimtarget,
    5134                                  $this->legendcsimalt,$this->legendcsimwintarget);   
    5135     }
    5136        
     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
    51375577} // Class
    51385578
    51395579
    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 //===================================================
    5148 class 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     }
     5580// Provide a deterministic list of new colors whenever the getColor() method
     5581// is called. Used to automatically set colors of plots.
     5582class 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
    52415627}
    52425628
  • trunk/client/modules/Elezioni/grafici/jpgraph_antispam-digits.php

    r267 r284  
    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 781 2006-10-08 08:07:47Z ljp $
     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 $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. All rights reserved.
    99//========================================================================
    1010
     
    1313    public $iHeight=30, $iWidth=30;
    1414
    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     } 
     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=' ;
     152    }
    153153}
    154154
    155155class AntiSpam {
    156156
    157     var $iNumber='';
    158 
    159     function AntiSpam($aNumber='') {
    160         $this->iNumber = $aNumber;
     157    private $iNumber='';
     158
     159    function __construct($aNumber='') {
     160        $this->iNumber = $aNumber;
    161161    }
    162162
    163163    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;
     164        $d='';
     165        for($i=0; $i < $aLen; ++$i) {
     166            $d .= rand(1,9);
     167        }
     168        $this->iNumber = $d;
     169        return $d;
    170170    }
    171171
    172172    function Stroke() {
    173173
    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;
     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;
    202202    }
    203203}
  • trunk/client/modules/Elezioni/grafici/jpgraph_antispam.php

    r267 r284  
    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 808 2006-11-28 19:10:40Z ljp $
     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 $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. All rights reserved.
    99//========================================================================
    1010
     
    1313    public $iHeight=30, $iWidth=30;
    1414
    15     function HandDigits() {
    16 
    17 //==========================================================
    18 // lj-small.jpg
    19 //==========================================================
    20 $this->chars['j'][0]= 658 ;
    21 $this->chars['j'][1]=
     15    function __construct() {
     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     } 
     543    }
    544544}
    545545
     
    549549    private $iDD=null;
    550550
    551     function AntiSpam($aData='') {
    552         $this->iData = $aData;
    553         $this->iDD = new HandDigits(); 
     551    function __construct($aData='') {
     552        $this->iData = $aData;
     553        $this->iDD = new HandDigits();
    554554    }
    555555
    556556    function Set($aData) {
    557         $this->iData = $aData;
     557        $this->iData = $aData;
    558558    }
    559559
    560560    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;
     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;
    577577    }
    578578
    579579    function Stroke() {
    580580
    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;
     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;
    612612    }
    613613}
  • trunk/client/modules/Elezioni/grafici/jpgraph_bar.php

    r267 r284  
    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 1017 2008-07-08 06:09:28Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1905 2009-10-06 18:00:21Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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        
    45 //---------------
    46 // CONSTRUCTOR
    47     function BarPlot($datay,$datax=false) {
    48         $this->Plot($datay,$datax);             
    49         ++$this->numpoints;
    50     }
    51 
    52 //---------------
    53 // PUBLIC METHODS       
    54        
     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
    5557    // Set a drop shadow for the bar (or rather an "up-right" shadow)
    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                
     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
    6676    // DEPRECATED use SetYBase instead
    6777    function SetYMin($aYStartValue) {
    68         //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");           
    69         $this->ybase=$aYStartValue;
     78        //die("JpGraph Error: Deprecated function SetYMin. Use SetYBase() instead.");
     79        $this->ybase=$aYStartValue;
    7080    }
    7181
    7282    // Specify the base value for the bars
    7383    function SetYBase($aYStartValue) {
    74         $this->ybase=$aYStartValue;
    75     }
    76        
     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
    77101    function Legend($graph) {
    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         }
     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        }
    110135    }
    111136
    112137    // Gets called before any axis are stroked
    113138    function PreStrokeAdjust($graph) {
    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 ) {
     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 ) {
    144169                // Not set
    145                 // set width to a visuable sensible default
    146                 $this->abswidth = $graph->img->plotwidth/(2*$this->numpoints);
    147             }
    148         }
     170                // set width to a visuable sensible default
     171                $this->abswidth = $graph->img->plotwidth/(2*$this->numpoints);
     172            }
     173        }
    149174    }
    150175
    151176    function Min() {
    152         $m = parent::Min();
    153         if( $m[1] >= $this->ybase )
    154             $m[1] = $this->ybase;
    155         return $m;     
     177        $m = parent::Min();
     178        if( $m[1] >= $this->ybase ) $m[1] = $this->ybase;
     179        return $m;
    156180    }
    157181
    158182    function Max() {
    159         $m = parent::Max();
    160         if( $m[1] <= $this->ybase )
    161             $m[1] = $this->ybase;
    162         return $m;     
    163     }   
    164        
     183        $m = parent::Max();
     184        if( $m[1] <= $this->ybase ) $m[1] = $this->ybase;
     185        return $m;
     186    }
     187
    165188    // Specify width as fractions of the major stepo size
    166189    function SetWidth($aWidth) {
    167         if( $aWidth > 1 ) {
    168             // Interpret this as absolute width
    169             $this->abswidth=$aWidth;
    170         }
    171         else
    172             $this->width=$aWidth;
    173     }
    174        
     190        if( $aWidth > 1 ) {
     191            // Interpret this as absolute width
     192            $this->abswidth=$aWidth;
     193        }
     194        else {
     195            $this->width=$aWidth;
     196        }
     197    }
     198
    175199    // Specify width in absolute pixels. If specified this
    176200    // overrides SetWidth()
    177201    function SetAbsWidth($aWidth) {
    178         $this->abswidth=$aWidth;
    179     }
    180                
     202        $this->abswidth=$aWidth;
     203    }
     204
    181205    function SetAlign($aAlign) {
    182         $this->align=$aAlign;
    183     }
    184        
     206        $this->align=$aAlign;
     207    }
     208
    185209    function SetNoFill() {
    186         $this->grad = false;
    187         $this->fill_color=false;
    188         $this->fill=false;
    189     }
    190                
     210        $this->grad = false;
     211        $this->fill_color=false;
     212        $this->fill=false;
     213    }
     214
    191215    function SetFillColor($aColor) {
    192         $this->fill = true ;
    193         $this->fill_color=$aColor;
    194     }
    195        
     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
    196226    function SetFillGradient($aFromColor,$aToColor=null,$aStyle=null) {
    197         $this->grad = true;
    198         $this->grad_fromcolor = $aFromColor;
    199         $this->grad_tocolor   = $aToColor;
    200         $this->grad_style     = $aStyle;
    201     }
    202        
     227        $this->grad = true;
     228        $this->grad_fromcolor = $aFromColor;
     229        $this->grad_tocolor   = $aToColor;
     230        $this->grad_style     = $aStyle;
     231    }
     232
    203233    function SetValuePos($aPos) {
    204         $this->valuepos = $aPos;
     234        $this->valuepos = $aPos;
    205235    }
    206236
    207237    function SetPattern($aPattern, $aColor='black'){
    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         }
     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        }
    231262    }
    232263
    233264    function _SetPatternHelper($aPattern, &$aPatternValue, &$aDensity){
    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;
     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;
    579672    }
    580673} // Class
     
    585678//===================================================
    586679class GroupBarPlot extends BarPlot {
    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       
     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
    608702    function Legend($graph) {
    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        
     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
    620714    function Min() {
    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        
     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
    631725    function Max() {
    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        
     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
    642736    function GetCSIMareas() {
    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        
     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
    651745    // Stroke all the bars next to each other
    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;
     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;
    670764    }
    671765} // Class
     
    676770//===================================================
    677771class AccBarPlot extends BarPlot {
    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       
     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
    707806    function Legend($graph) {
    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         }
     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        }
    717816    }
    718817
    719818    function Max() {
    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);
     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);
    755854    }
    756855
    757856    function Min() {
    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);
     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);
    787886    }
    788887
    789888    // Stroke acc bar plot
    790889    function Stroke($img,$xscale,$yscale) {
    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;
     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;
    10381185    }
    10391186} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_canvas.php

    r267 r284  
    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 781 2006-10-08 08:07:47Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1923 2010-01-11 13:48:49Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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 CanvasGraph($aWidth=300,$aHeight=200,$aCachedName="",$timeout=0,$inline=1) {
    24         $this->Graph($aWidth,$aHeight,$aCachedName,$timeout,$inline);
     21    //---------------
     22    // CONSTRUCTOR
     23    function __construct($aWidth=300,$aHeight=200,$aCachedName="",$timeout=0,$inline=1) {
     24        parent::__construct($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') ) {
    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        
     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                }
    7870
    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         }
     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        }
    9191    }
    9292} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_canvtools.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1857 2009-09-28 14:38:14Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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 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    
     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
    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;
     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);
    4448    }
    4549
    4650    function Translate($x,$y) {
    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);
     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);
    5054    }
    5155
    5256    function TranslateX($x) {
    53         $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
    54         return $xp;
     57        $xp = round(($x-$this->ixmin)/($this->ixmax - $this->ixmin) * $this->w);
     58        return $xp;
    5559    }
    5660
    5761    function TranslateY($y) {
    58         $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
    59         return $yp;
     62        $yp = round(($y-$this->iymin)/($this->iymax - $this->iymin) * $this->h);
     63        return $yp;
    6064    }
    6165
     
    7074    private $img,$scale;
    7175
    72     function Shape($aGraph,$scale) {
    73         $this->img = $aGraph->img;
    74         $this->img->SetColor('black');
    75         $this->scale = $scale;
     76    function __construct($aGraph,$scale) {
     77        $this->img = $aGraph->img;
     78        $this->img->SetColor('black');
     79        $this->scale = $scale;
    7680    }
    7781
    7882    function SetColor($aColor) {
    79         $this->img->SetColor($aColor);
     83        $this->img->SetColor($aColor);
    8084    }
    8185
    8286    function Line($x1,$y1,$x2,$y2) {
    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);
     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);
    8694    }
    8795
    8896    function Polygon($p,$aClosed=false) {
    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);
     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);
    95103    }
    96104
    97105    function FilledPolygon($p) {
    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    
     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
    106114
    107115    // Draw a bezier curve with defining points in the $aPnts array
     
    112120    // 6=x3, 7=y3
    113121    function Bezier($p,$aSteps=40) {
    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]);
     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]);
    138146    }
    139147
    140148    function 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);
     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);
    144152    }
    145153
    146154    function FilledRectangle($x1,$y1,$x2,$y2) {
    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    
     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
    152160    function 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);
     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);
    159167    }
    160168
    161169    function FilledCircle($x1,$y1,$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);   
     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);
    194202    }
    195203
    196204    function ShadowRectangle($x1,$y1,$x2,$y2,$fcolor=false,$shadow_width=null,$shadow_color=array(102,102,102)) {
    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);
     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);
    204212    }
    205213
    206214    function SetTextAlign($halign,$valign="bottom") {
    207         $this->img->SetTextAlign($halign,$valign="bottom");
     215        $this->img->SetTextAlign($halign,$valign="bottom");
    208216    }
    209217
    210218    function StrokeText($x1,$y1,$txt,$dir=0,$paragraph_align="left") {
    211         list($x1,$y1) = $this->scale->Translate($x1,$y1);
    212         $this->img->StrokeText($x1,$y1,$txt,$dir,$paragraph_align);
     219        list($x1,$y1) = $this->scale->Translate($x1,$y1);
     220        $this->img->StrokeText($x1,$y1,$txt,$dir,$paragraph_align);
    213221    }
    214222
     
    217225    // 0=Top left, 1=top right, 2=bottom right, 3=bottom left
    218226    function IndentedRectangle($xt,$yt,$w,$h,$iw=0,$ih=0,$aCorner=3,$aFillColor="",$r=4) {
    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         }
     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        }
    366374    }
    367375}
     
    370378//===================================================
    371379// CLASS RectangleText
    372 // Description: Draws a text paragraph inside a 
     380// Description: Draws a text paragraph inside a
    373381// rounded, possible filled, rectangle.
    374382//===================================================
     
    380388    private $iShadowWidth=3,$iShadowColor='';
    381389
    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  
     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
    390398    function SetShadow($aColor='gray',$aWidth=3) {
    391         $this->iShadowColor = $aColor;
    392         $this->iShadowWidth = $aWidth;
     399        $this->iShadowColor = $aColor;
     400        $this->iShadowWidth = $aWidth;
    393401    }
    394402
    395403    function SetFont($FontFam,$aFontStyle,$aFontSize=12) {
    396         $this->iTxt->SetFont($FontFam,$aFontStyle,$aFontSize);
     404        $this->iTxt->SetFont($FontFam,$aFontStyle,$aFontSize);
    397405    }
    398406
    399407    function SetTxt($aTxt) {
    400         $this->iTxt->Set($aTxt);
     408        $this->iTxt->Set($aTxt);
    401409    }
    402410
    403411    function ParagraphAlign($aParaAlign) {
    404         $this->iParaAlign = $aParaAlign;
     412        $this->iParaAlign = $aParaAlign;
    405413    }
    406414
    407415    function SetFillColor($aFillColor) {
    408         $this->iFillColor = $aFillColor;
     416        $this->iFillColor = $aFillColor;
    409417    }
    410418
    411419    function SetAutoMargin($aMargin) {
    412         $this->iAutoBoxMargin=$aMargin;
     420        $this->iAutoBoxMargin=$aMargin;
    413421    }
    414422
    415423    function SetColor($aColor) {
    416         $this->iColor = $aColor;
     424        $this->iColor = $aColor;
    417425    }
    418426
    419427    function SetFontColor($aColor) {
    420         $this->iFontColor = $aColor;
     428        $this->iFontColor = $aColor;
    421429    }
    422430
    423431    function SetPos($xl=0,$yt=0,$w=0,$h=0) {
    424         $this->ix = $xl;
    425         $this->iy = $yt;
    426         $this->iw = $w;
    427         $this->ih = $h;
     432        $this->ix = $xl;
     433        $this->iy = $yt;
     434        $this->iw = $w;
     435        $this->ih = $h;
    428436    }
    429437
    430438    function Pos($xl=0,$yt=0,$w=0,$h=0) {
    431         $this->ix = $xl;
    432         $this->iy = $yt;
    433         $this->iw = $w;
    434         $this->ih = $h;
     439        $this->ix = $xl;
     440        $this->iy = $yt;
     441        $this->iw = $w;
     442        $this->ih = $h;
    435443    }
    436444
    437445    function Set($aTxt,$xl,$yt,$w=0,$h=0) {
    438         $this->iTxt->Set($aTxt);
    439         $this->ix = $xl;
    440         $this->iy = $yt;
    441         $this->iw = $w;
    442         $this->ih = $h;
     446        $this->iTxt->Set($aTxt);
     447        $this->ix = $xl;
     448        $this->iy = $yt;
     449        $this->iw = $w;
     450        $this->ih = $h;
    443451    }
    444452
    445453    function SetCornerRadius($aRad=5) {
    446         $this->ir = $aRad;
     454        $this->ir = $aRad;
    447455    }
    448456
    449457    function Stroke($aImg,$scale) {
    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);
     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);
    509517
    510518    }
  • trunk/client/modules/Elezioni/grafici/jpgraph_date.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1106 2009-02-22 20:16:35Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. All rights reserved.
     9 //========================================================================
     10 */
    1111
    1212define('HOURADJ_1',0+30);
     
    5252    private $iStartTimeAlign = false, $iEndTimeAlign = false;
    5353
    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 //------------------------------------------------------------------------------------------
     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    //------------------------------------------------------------------------------------------
    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

    r267 r284  
    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 973 2008-03-09 15:29:44Z 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 1920 2009-12-08 10:02:26Z ljp $
    99//
    1010// Copyright 2006 (c) Aditus Consulting. All rights reserved.
    1111//========================================================================
    1212
     13if( !defined('DEFAULT_ERR_LOCALE') ) {
     14    define('DEFAULT_ERR_LOCALE','en');
     15}
     16
     17if( !defined('USE_IMAGE_ERROR_HANDLER') ) {
     18    define('USE_IMAGE_ERROR_HANDLER',true);
     19}
    1320
    1421GLOBAL $__jpg_err_locale ;
     
    1724class ErrMsgText {
    1825    private $lt=NULL;
    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;
     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;
    3441    }
    3542
    3643    function Get($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
    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 
     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     
    8996//
    9097// A wrapper class that is used to access the specified error object
     
    93100//
    94101class JpGraphError {
    95     private static $__jpg_err;
    96     public static function Install($aErrObject) {
    97         self::$__jpg_err = new $aErrObject;
    98     }
     102    private static $__iImgFlg = true;
     103    private static $__iLogFile = '';
     104    private static $__iTitle = 'JpGraph Error: ';
    99105    public static function Raise($aMsg,$aHalt=true){
    100         self::$__jpg_err->Raise($aMsg,$aHalt);
     106        throw new JpGraphException($aMsg);
    101107    }
    102108    public static function SetErrLocale($aLoc) {
    103         GLOBAL $__jpg_err_locale ;
    104         $__jpg_err_locale = $aLoc;
     109        GLOBAL $__jpg_err_locale ;
     110        $__jpg_err_locale = $aLoc;
    105111    }
    106112    public static function RaiseL($errnbr,$a1=null,$a2=null,$a3=null,$a4=null,$a5=null) {
    107         $t = new ErrMsgText();
    108         $msg = $t->Get($errnbr,$a1,$a2,$a3,$a4,$a5);
    109         self::$__jpg_err->Raise($msg);
    110     }
    111 }
     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
     135class 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
     173class 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
     184global $__jpg_OldHandler;
     185$__jpg_OldHandler = set_exception_handler(array('JpGraphException','defaultHandler'));
    112186
    113187//
     
    120194class JpGraphErrObject {
    121195
    122     protected $iTitle = "JpGraph Error";
     196    protected $iTitle = "JpGraph error: ";
    123197    protected $iDest = false;
    124198
    125199
    126     function JpGraphErrObject() {
    127         // Empty. Reserved for future use
     200    function __construct() {
     201        // Empty. Reserved for future use
    128202    }
    129203
    130204    function SetTitle($aTitle) {
    131         $this->iTitle = $aTitle;
    132     }
    133 
    134     function SetStrokeDest($aDest) { 
    135         $this->iDest = $aDest;
     205        $this->iTitle = $aTitle;
     206    }
     207
     208    function SetStrokeDest($aDest) {
     209        $this->iDest = $aDest;
    136210    }
    137211
    138212    // If aHalt is true then execution can't continue. Typical used for fatal errors
    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();
     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);
    153240    }
    154241}
     
    158245//==============================================================
    159246class JpGraphErrObjectImg extends JpGraphErrObject {
     247   
     248    function __construct() {
     249        parent::__construct();
     250        // Empty. Reserved for future use
     251    }
    160252
    161253    function Raise($aMsg,$aHalt=true) {
    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
    270 if( USE_IMAGE_ERROR_HANDLER ) {
    271     JpGraphError::Install("JpGraphErrObjectImg");
    272 }
    273 else {
    274     JpGraphError::Install("JpGraphErrObject");
    275 }
    276 
    277 
     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
     366if( ! USE_IMAGE_ERROR_HANDLER ) {
     367        JpGraphError::SetImageFlag(false);
     368}
    278369?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_error.php

    r267 r284  
    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 781 2006-10-08 08:07:47Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1106 2009-02-22 20:16:35Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. All rights reserved.
     9 //========================================================================
     10 */
     11   
    1212//===================================================
    1313// CLASS ErrorPlot
     
    1717class ErrorPlot extends Plot {
    1818    private $errwidth=2;
    19 //---------------
    20 // CONSTRUCTOR
    21     function ErrorPlot($datay,$datax=false) {
    22         $this->Plot($datay,$datax);
    23         $this->numpoints /= 2;
     19   
     20    //---------------
     21    // CONSTRUCTOR
     22    function __construct($datay,$datax=false) {
     23        parent::__construct($datay,$datax);
     24        $this->numpoints /= 2;
    2425    }
    25 //---------------
    26 // PUBLIC METHODS
    27        
     26    //---------------
     27    // PUBLIC METHODS
     28
    2829    // Gets called before any axis are stroked
    2930    function PreStrokeAdjust($graph) {
    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();
     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();
    3940    }
    40        
     41
    4142    // Method description
    4243    function Stroke($img,$xscale,$yscale) {
    43         $numpoints=count($this->coords[0])/2;
    44         $img->SetColor($this->color);
    45         $img->SetLineWeight($this->weight);     
     44        $numpoints=count($this->coords[0])/2;
     45        $img->SetColor($this->color);
     46        $img->SetLineWeight($this->weight);
    4647
    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;
     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;
    5657
    57         for( $i=0; $i<$numpoints; ++$i) {
    58             if( $exist_x )
    59                 $x=$this->coords[1][$i];
    60             else
    61                 $x=$i;
     58        for( $i=0; $i<$numpoints; ++$i) {
     59            if( $exist_x )
     60            $x=$this->coords[1][$i];
     61            else
     62            $x=$i;
    6263
    63             if( !is_numeric($x) || 
    64                 !is_numeric($this->coords[0][$i*2]) || !is_numeric($this->coords[0][$i*2+1]) ) {
    65                 continue;
    66             }
     64            if( !is_numeric($x) ||
     65            !is_numeric($this->coords[0][$i*2]) || !is_numeric($this->coords[0][$i*2+1]) ) {
     66                continue;
     67            }
    6768
    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;
     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;
    7677    }
    7778} // Class
     
    8687class ErrorLinePlot extends ErrorPlot {
    8788    public $line=null;
    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);
     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);
    9899    }
    99100
    100 //---------------
    101 // PUBLIC METHODS
     101    //---------------
     102    // PUBLIC METHODS
    102103    function Legend($graph) {
    103         if( $this->legend != "" )
    104             $graph->legend->Add($this->legend,$this->color);
    105         $this->line->Legend($graph);
     104        if( $this->legend != "" )
     105        $graph->legend->Add($this->legend,$this->color);
     106        $this->line->Legend($graph);
    106107    }
    107                        
     108     
    108109    function Stroke($img,$xscale,$yscale) {
    109         parent::Stroke($img,$xscale,$yscale);
    110         $this->line->Stroke($img,$xscale,$yscale);
     110        parent::Stroke($img,$xscale,$yscale);
     111        $this->line->Stroke($img,$xscale,$yscale);
    111112    }
    112113} // Class
     
    119120class LineErrorPlot extends ErrorPlot {
    120121    public $line=null;
    121 //---------------
    122 // CONSTRUCTOR
     122    //---------------
     123    // CONSTRUCTOR
    123124    // Data is (val, errdeltamin, errdeltamax)
    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);
     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);
    138139    }
    139140
    140 //---------------
    141 // PUBLIC METHODS
     141    //---------------
     142    // PUBLIC METHODS
    142143    function Legend($graph) {
    143         if( $this->legend != "" )
    144             $graph->legend->Add($this->legend,$this->color);
    145         $this->line->Legend($graph);
     144        if( $this->legend != "" )
     145        $graph->legend->Add($this->legend,$this->color);
     146        $this->line->Legend($graph);
    146147    }
    147                        
     148     
    148149    function Stroke($img,$xscale,$yscale) {
    149         parent::Stroke($img,$xscale,$yscale);
    150         $this->line->Stroke($img,$xscale,$yscale);
     150        parent::Stroke($img,$xscale,$yscale);
     151        $this->line->Stroke($img,$xscale,$yscale);
    151152    }
    152153} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_flags.php

    r267 r284  
    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 957 2007-12-01 14:00:29Z ljp $
     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 $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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 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);
     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);
    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             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         }
     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        }
    332331    }
    333332
    334333    function GetIdxByName($aName,&$outFullName) {
    335334
    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         }
     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        }
    370367    }
    371368}
  • trunk/client/modules/Elezioni/grafici/jpgraph_gantt.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1809 2009-09-09 13:07:33Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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',4000);
     17define('MAX_GANTTIMG_SIZE_W',8000);
    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 GanttActivityInfo() {
    156         $this->vgrid = new LineProperty();
     155    function __construct() {
     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,
    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         }
     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        }
    323322    }
    324323}
     
    330329//===================================================
    331330class GanttGraph extends Graph {
    332     public $scale;              // Public accessible
     331    public $scale;  // Public accessible
    333332    public $hgrid=null;
    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
     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
    338337    private $iSimpleFont = FF_FONT1,$iSimpleFontSize=11;
    339338    private $iSimpleStyle=GANTT_RDIAG,$iSimpleColor='yellow',$iSimpleBkgColor='red';
    340339    private $iSimpleProgressBkgColor='gray',$iSimpleProgressColor='darkgreen';
    341340    private $iSimpleProgressStyle=GANTT_SOLID;
    342 //---------------
    343 // CONSTRUCTOR 
     341    private $iZoomFactor = 1.0;
     342    //---------------
     343    // CONSTRUCTOR
    344344    // Create a new gantt graph
    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     // 
     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    //
    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        
     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
    475480    // Set what headers should be shown
    476481    function ShowHeaders($aFlg) {
    477         $this->scale->ShowHeaders($aFlg);
    478     }
    479        
    480     // Specify the fraction of the font height that should be added 
     482        $this->scale->ShowHeaders($aFlg);
     483    }
     484
     485    // Specify the fraction of the font height that should be added
    481486    // as vertical margin
    482487    function SetLabelVMarginFactor($aVal) {
    483         $this->iLabelVMarginFactor = $aVal;
     488        $this->iLabelVMarginFactor = $aVal;
    484489    }
    485490
    486491    // Synonym to the method above
    487492    function SetVMarginFactor($aVal) {
    488         $this->iLabelVMarginFactor = $aVal;
    489     }
    490        
    491        
     493        $this->iLabelVMarginFactor = $aVal;
     494    }
     495
     496
    492497    // Add a new Gantt object
    493498    function Add($aObject) {
    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             }
     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        }
    504542        }
    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     }
    514543
    515544    // Override inherit method from Graph and give a warning message
    516545    function SetScale($aAxisType,$aYMin=1,$aYMax=1,$aXMin=1,$aXMax=1) {
    517         JpGraphError::RaiseL(6005);
    518 //("SetScale() is not meaningfull with Gantt charts.");
     546        JpGraphError::RaiseL(6005);
     547        //("SetScale() is not meaningfull with Gantt charts.");
    519548    }
    520549
     
    522551    // automtically determined from the input data)
    523552    function SetDateRange($aStart,$aEnd) {
    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        
     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
    533562    // Get the maximum width of the activity titles columns for the bars
    534563    // The name is lightly misleading since we from now on can have
     
    536565    // it only supported a single label, hence the name.
    537566    function GetMaxLabelWidth() {
    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        
     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
    556585    // Get the maximum height of the titles for the bars
    557586    function GetMaxLabelHeight() {
    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;
     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;
    568599    }
    569600
    570601    function GetMaxBarAbsHeight() {
    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        
     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
    582613    // Get the maximum used line number (vertical position) for bars
    583614    function GetBarMaxLineNumber() {
    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        
     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
    595626    // Get the minumum and maximum used dates for all bars
    596627    function GetBarMinMax() {
    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);
     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);
    622653    }
    623654
     
    628659    function AutoSize() {
    629660
    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 :
     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 :
    700745                        $txt =  "Mon 23/6";
    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 :
     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 :
    709754                        $txt =  "23/6";
    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         }
     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        }
    879925    }
    880926
     
    884930    // must walk through all the objects, sigh...
    885931    function GetMaxActInfoColWidth() {
    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;
     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;
    902948    }
    903949
    904950    // Stroke the gantt chart
    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         }
     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        }
    10071056    }
    10081057
    10091058    function StrokeConstrains() {
    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         }
     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        }
    10911140    }
    10921141
    10931142    function GetCSIMAreas() {
    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;
     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;
    11051154    }
    11061155}
     
    11281177
    11291178    function GetLen() {
    1130         return $this->iLen ;
     1179        return $this->iLen ;
    11311180    }
    11321181
    11331182    function GetImg($aIdx) {
    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         //==========================================================
     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        //==========================================================
    13601409        $this->iBuiltinIcon[11][0]= 1824 ;
    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);
     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);
    14191468    }
    14201469}
     
    14271476//===================================================
    14281477// CLASS IconImage
    1429 // Description: Holds properties for an icon image 
     1478// Description: Holds properties for an icon image
    14301479//===================================================
    14311480class IconImage {
     
    14351484    private $iScale=1.0;
    14361485
    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);
     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);
    14531502    }
    14541503
    14551504    function GetWidth() {
    1456         return round($this->iScale*$this->iWidth);
     1505        return round($this->iScale*$this->iWidth);
    14571506    }
    14581507
    14591508    function GetHeight() {
    1460         return round($this->iScale*$this->iHeight);
     1509        return round($this->iScale*$this->iHeight);
    14611510    }
    14621511
    14631512    function SetAlign($aX='left',$aY='center') {
    1464 
    1465         $this->ixalign = $aX;
    1466         $this->iyalign = $aY;
    1467 
     1513        $this->ixalign = $aX;
     1514        $this->iyalign = $aY;
    14681515    }
    14691516
    14701517    function Stroke($aImg,$x,$y) {
    14711518
    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);
     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);
    14901537    }
    14911538}
     
    15001547    public $csimtarget='',$csimwintarget='',$csimalt='';
    15011548    private $iFFamily=FF_FONT1,$iFStyle=FS_NORMAL,$iFSize=10;
     1549    private $iFontArray=array();
    15021550    private $iColor="black";
    15031551    private $iText="";
    15041552    private $iHAlign="left",$iVAlign="bottom";
    1505        
    1506 //---------------
    1507 // CONSTRUCTOR 
    1508     function TextProperty($aTxt='') {
    1509         $this->iText = $aTxt;
    1510     }           
    1511        
    1512 //---------------
    1513 // PUBLIC METHODS       
     1553
     1554    //---------------
     1555    // CONSTRUCTOR
     1556    function __construct($aTxt='') {
     1557        $this->iText = $aTxt;
     1558    }
     1559
     1560    //---------------
     1561    // PUBLIC METHODS
    15141562    function Set($aTxt) {
    1515         $this->iText = $aTxt;
     1563        $this->iText = $aTxt;
    15161564    }
    15171565
    15181566    function SetCSIMTarget($aTarget,$aAltText='',$aWinTarget='') {
    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);
     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);
    15291577        $this->csimalt=$aAltText;
    1530        
    1531     }
    1532    
     1578
     1579    }
     1580
    15331581    function SetCSIMAlt($aAltText) {
    1534         if( is_string($aAltText) )
    1535             $aAltText = array($aAltText);
     1582        if( is_string($aAltText) )
     1583        $aAltText = array($aAltText);
    15361584        $this->csimalt=$aAltText;
    15371585    }
     
    15391587    // Set text color
    15401588    function SetColor($aColor) {
    1541         $this->iColor = $aColor;
    1542     }
    1543        
     1589        $this->iColor = $aColor;
     1590    }
     1591
    15441592    function HasTabs() {
    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        
     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
    15531601    // Get number of tabs in string
    15541602    function GetNbrTabs() {
    1555         if( is_string($this->iText) ) {
    1556             return substr_count($this->iText,"\t") ;
    1557         }
    1558         else{
    1559             return 0;
    1560         }
    1561     }
    1562        
     1603        if( is_string($this->iText) ) {
     1604            return substr_count($this->iText,"\t") ;
     1605        }
     1606        else{
     1607            return 0;
     1608        }
     1609    }
     1610
    15631611    // Set alignment
    15641612    function Align($aHAlign,$aVAlign="bottom") {
    1565         $this->iHAlign=$aHAlign;
    1566         $this->iVAlign=$aVAlign;
    1567     }
    1568        
     1613        $this->iHAlign=$aHAlign;
     1614        $this->iVAlign=$aVAlign;
     1615    }
     1616
    15691617    // Synonym
    15701618    function SetAlign($aHAlign,$aVAlign="bottom") {
    1571         $this->iHAlign=$aHAlign;
    1572         $this->iVAlign=$aVAlign;
    1573     }
    1574        
     1619        $this->iHAlign=$aHAlign;
     1620        $this->iVAlign=$aVAlign;
     1621    }
     1622
    15751623    // Specify font
    15761624    function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
    1577         $this->iFFamily = $aFFamily;
    1578         $this->iFStyle   = $aFStyle;
    1579         $this->iFSize    = $aFSize;
    1580     }
     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
    15811638
    15821639    function IsColumns() {
    1583         return is_array($this->iText) ;
    1584     }
    1585        
     1640        return is_array($this->iText) ;
     1641    }
     1642
    15861643    // Get width of text. If text contains several columns separated by
    1587     // tabs then return both the total width as well as an array with a 
     1644    // tabs then return both the total width as well as an array with a
    15881645    // width for each column.
    15891646    function GetWidth($aImg,$aUseTabs=false,$aTabExtraMargin=1.1) {
    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         }
     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        }
    16341698    }
    16351699
     
    16381702    // column as an array of one
    16391703    function GetColWidth($aImg,$aMargin=0) {
    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        
     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
    16621733    // Get total height of text
    16631734    function GetHeight($aImg) {
    1664         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1665         return $aImg->GetFontHeight();
    1666     }
    1667        
    1668     // Unhide/hide the text     
     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
    16691755    function Show($aShow=true) {
    1670         $this->iShow=$aShow;
    1671     }
    1672        
     1756        $this->iShow=$aShow;
     1757    }
     1758
    16731759    // Stroke text at (x,y) coordinates. If the text contains tabs then the
    16741760    // x parameter should be an array of positions to be used for each successive
    16751761    // tab mark. If no array is supplied then the tabs will be ignored.
    16761762    function Stroke($aImg,$aX,$aY) {
    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         }
     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        }
    17241824    }
    17251825}
     
    17271827//===================================================
    17281828// CLASS HeaderProperty
    1729 // Description: Data encapsulating class to hold property 
     1829// Description: Data encapsulating class to hold property
    17301830// for each type of the scale headers
    17311831//===================================================
     
    17421842    public $iIntervall = 1;
    17431843
    1744 //---------------
    1745 // CONSTRUCTOR 
    1746     function HeaderProperty() {
    1747         $this->grid = new LineProperty();
    1748     }
    1749 
    1750 //---------------
    1751 // PUBLIC METHODS               
     1844    //---------------
     1845    // CONSTRUCTOR
     1846    function __construct() {
     1847        $this->grid = new LineProperty();
     1848    }
     1849
     1850    //---------------
     1851    // PUBLIC METHODS
    17521852    function Show($aShow=true) {
    1753         $this->iShowLabels = $aShow;
     1853        $this->iShowLabels = $aShow;
    17541854    }
    17551855
    17561856    function SetIntervall($aInt) {
    1757         $this->iIntervall = $aInt;
     1857        $this->iIntervall = $aInt;
     1858    }
     1859
     1860    function SetInterval($aInt) {
     1861        $this->iIntervall = $aInt;
    17581862    }
    17591863
    17601864    function GetIntervall() {
    1761         return $this->iIntervall ;
    1762     }
    1763        
     1865        return $this->iIntervall ;
     1866    }
     1867
    17641868    function SetFont($aFFamily,$aFStyle=FS_NORMAL,$aFSize=10) {
    1765         $this->iFFamily = $aFFamily;
    1766         $this->iFStyle  = $aFStyle;
    1767         $this->iFSize    = $aFSize;
     1869        $this->iFFamily = $aFFamily;
     1870        $this->iFStyle = $aFStyle;
     1871        $this->iFSize = $aFSize;
    17681872    }
    17691873
    17701874    function SetFontColor($aColor) {
    1771         $this->iTextColor = $aColor;
    1772     }
    1773        
     1875        $this->iTextColor = $aColor;
     1876    }
     1877
    17741878    function GetFontHeight($aImg) {
    1775         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1776         return $aImg->GetFontHeight();
     1879        $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1880        return $aImg->GetFontHeight();
    17771881    }
    17781882
    17791883    function GetFontWidth($aImg) {
    1780         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1781         return $aImg->GetFontWidth();
     1884        $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1885        return $aImg->GetFontWidth();
    17821886    }
    17831887
    17841888    function GetStrWidth($aImg,$aStr) {
    1785         $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
    1786         return $aImg->GetTextWidth($aStr);
    1787     }
    1788        
     1889        $aImg->SetFont($this->iFFamily,$this->iFStyle,$this->iFSize);
     1890        return $aImg->GetTextWidth($aStr);
     1891    }
     1892
    17891893    function SetStyle($aStyle) {
    1790         $this->iStyle = $aStyle;
    1791     }
    1792        
     1894        $this->iStyle = $aStyle;
     1895    }
     1896
    17931897    function SetBackgroundColor($aColor) {
    1794         $this->iBackgroundColor=$aColor;
     1898        $this->iBackgroundColor=$aColor;
    17951899    }
    17961900
    17971901    function SetFrameWeight($aWeight) {
    1798         $this->iFrameWeight=$aWeight;
     1902        $this->iFrameWeight=$aWeight;
    17991903    }
    18001904
    18011905    function SetFrameColor($aColor) {
    1802         $this->iFrameColor=$aColor;
    1803     }
    1804        
     1906        $this->iFrameColor=$aColor;
     1907    }
     1908
    18051909    // Only used by day scale
    18061910    function SetWeekendColor($aColor) {
    1807         $this->iWeekendBackgroundColor=$aColor;
    1808     }
    1809        
     1911        $this->iWeekendBackgroundColor=$aColor;
     1912    }
     1913
    18101914    // Only used by day scale
    18111915    function SetSundayFontColor($aColor) {
    1812         $this->iSundayTextColor=$aColor;
    1813     }
    1814        
     1916        $this->iSundayTextColor=$aColor;
     1917    }
     1918
    18151919    function SetTitleVertMargin($aMargin) {
    1816         $this->iTitleVertMargin=$aMargin;
    1817     }
    1818        
     1920        $this->iTitleVertMargin=$aMargin;
     1921    }
     1922
    18191923    function SetLabelFormatString($aStr) {
    1820         $this->iLabelFormStr=$aStr;
     1924        $this->iLabelFormStr=$aStr;
    18211925    }
    18221926
    18231927    function SetFormatString($aStr) {
    1824         $this->SetLabelFormatString($aStr);
     1928        $this->SetLabelFormatString($aStr);
    18251929    }
    18261930
     
    18441948    public $actinfo;
    18451949    public $iTopPlotMargin=10,$iBottomPlotMargin=15;
    1846     public $iVertLines=-1;     
     1950    public $iVertLines=-1;
    18471951    public $iVertHeaderSize=-1;
    18481952    // The width of the labels (defaults to the widest of all labels)
    1849     private $iLabelWidth;       
     1953    private $iLabelWidth;
    18501954    // Out image to stroke the scale to
    1851     private $iImg;     
     1955    private $iImg;
    18521956    private $iTableHeaderBackgroundColor="white",$iTableHeaderFrameColor="black";
    18531957    private $iTableHeaderFrameWeight=1;
     
    18561960    private $iVertLayout=GANTT_EVEN;
    18571961    private $iUsePlotWeekendBackground=true;
    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       
     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
    19072011    // Specify what headers should be visible
    19082012    function ShowHeaders($aFlg) {
    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        
     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
    19262030    // Should the weekend background stretch all the way down in the plotarea
    19272031    function UseWeekendBackground($aShow) {
    1928         $this->iUsePlotWeekendBackground = $aShow;
    1929     }
    1930        
     2032        $this->iUsePlotWeekendBackground = $aShow;
     2033    }
     2034
    19312035    // Have a range been specified?
    19322036    function IsRangeSet() {
    1933         return $this->iStartDate!=-1 && $this->iEndDate!=-1;
    1934     }
    1935        
     2037        return $this->iStartDate!=-1 && $this->iEndDate!=-1;
     2038    }
     2039
    19362040    // Should the layout be from top or even?
    19372041    function SetVertLayout($aLayout) {
    1938         $this->iVertLayout = $aLayout;
    1939     }
    1940        
     2042        $this->iVertLayout = $aLayout;
     2043    }
     2044
    19412045    // Which locale should be used?
    19422046    function SetDateLocale($aLocale) {
    1943         $this->iDateLocale->Set($aLocale);
    1944     }
    1945        
     2047        $this->iDateLocale->Set($aLocale);
     2048    }
     2049
    19462050    // Number of days we are showing
    19472051    function GetNumberOfDays() {
    1948         return round(($this->iEndDate-$this->iStartDate)/SECPERDAY);
    1949     }
    1950        
     2052        return round(($this->iEndDate-$this->iStartDate)/SECPERDAY);
     2053    }
     2054
    19512055    // The width of the actual plot area
    19522056    function GetPlotWidth() {
    1953         $img=$this->iImg;
    1954         return $img->width - $img->left_margin - $img->right_margin;
     2057        $img=$this->iImg;
     2058        return $img->width - $img->left_margin - $img->right_margin;
    19552059    }
    19562060
     
    19592063    // widest title)
    19602064    function SetLabelWidth($aLabelWidth) {
    1961         $this->iLabelWidth=$aLabelWidth;
    1962     }
    1963 
    1964         // Which day should the week start?
    1965         // 0==Sun, 1==Monday, 2==Tuesday etc
     2065        $this->iLabelWidth=$aLabelWidth;
     2066    }
     2067
     2068    // Which day should the week start?
     2069    // 0==Sun, 1==Monday, 2==Tuesday etc
    19662070    function SetWeekStart($aStartDay) {
    1967         $this->iWeekStart = $aStartDay % 7;
    1968        
    1969         //Recalculate the startday since this will change the week start
    1970         $this->SetRange($this->iStartDate,$this->iEndDate);
     2071        $this->iWeekStart = $aStartDay % 7;
     2072
     2073        //Recalculate the startday since this will change the week start
     2074        $this->SetRange($this->iStartDate,$this->iEndDate);
    19712075    }
    19722076
    19732077    // Do we show min scale?
    19742078    function IsDisplayMinute() {
    1975         return $this->minute->iShowLabels;
     2079        return $this->minute->iShowLabels;
    19762080    }
    19772081
    19782082    // Do we show day scale?
    19792083    function IsDisplayHour() {
    1980         return $this->hour->iShowLabels;
    1981     }
    1982 
    1983        
     2084        return $this->hour->iShowLabels;
     2085    }
     2086
     2087
    19842088    // Do we show day scale?
    19852089    function IsDisplayDay() {
    1986         return $this->day->iShowLabels;
    1987     }
    1988        
     2090        return $this->day->iShowLabels;
     2091    }
     2092
    19892093    // Do we show week scale?
    19902094    function IsDisplayWeek() {
    1991         return $this->week->iShowLabels;
    1992     }
    1993        
     2095        return $this->week->iShowLabels;
     2096    }
     2097
    19942098    // Do we show month scale?
    19952099    function IsDisplayMonth() {
    1996         return $this->month->iShowLabels;
    1997     }
    1998        
     2100        return $this->month->iShowLabels;
     2101    }
     2102
    19992103    // Do we show year scale?
    20002104    function IsDisplayYear() {
    2001         return $this->year->iShowLabels;
     2105        return $this->year->iShowLabels;
    20022106    }
    20032107
    20042108    // Specify spacing (in percent of bar height) between activity bars
    20052109    function SetVertSpacing($aSpacing) {
    2006         $this->iVertSpacing = $aSpacing;
     2110        $this->iVertSpacing = $aSpacing;
    20072111    }
    20082112
     
    20102114    // Always round to the nearest week boundary
    20112115    function SetRange($aMin,$aMax) {
    2012         $this->iStartDate = $this->NormalizeDate($aMin);
    2013         $this->iEndDate = $this->NormalizeDate($aMax); 
     2116        $this->iStartDate = $this->NormalizeDate($aMin);
     2117        $this->iEndDate = $this->NormalizeDate($aMax);
    20142118    }
    20152119
     
    20192123    function AdjustStartEndDay() {
    20202124
    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)     
     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)
    20532157    function SetTableTitleBackground($aColor) {
    2054         $this->iTableHeaderBackgroundColor = $aColor;
    2055     }
    2056 
    2057 ///////////////////////////////////////
    2058 // PRIVATE Methods
    2059        
     2158        $this->iTableHeaderBackgroundColor = $aColor;
     2159    }
     2160
     2161    ///////////////////////////////////////
     2162    // PRIVATE Methods
     2163
    20602164    // Determine the height of all the scale headers combined
    20612165    function GetHeaderHeight() {
    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        
     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
    20912195    // Get width (in pixels) for a single day
    20922196    function GetDayWidth() {
    2093         return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays();   
     2197        return ($this->GetPlotWidth()-$this->iLabelWidth+1)/$this->GetNumberOfDays();
    20942198    }
    20952199
    20962200    // Get width (in pixels) for a single hour
    20972201    function GetHourWidth() {
    2098         return $this->GetDayWidth() / 24 ;
     2202        return $this->GetDayWidth() / 24 ;
    20992203    }
    21002204
    21012205    function GetMinuteWidth() {
    2102         return $this->GetHourWidth() / 60 ;
     2206        return $this->GetHourWidth() / 60 ;
    21032207    }
    21042208
    21052209    // Nuber of days in a year
    21062210    function GetNumDaysInYear($aYear) {
    2107         if( $this->IsLeap($aYear) )
    2108             return 366;
    2109         else
    2110             return 365;
    2111     }
    2112        
    2113     // Get week number 
     2211        if( $this->IsLeap($aYear) )
     2212        return 366;
     2213        else
     2214        return 365;
     2215    }
     2216
     2217    // Get week number
    21142218    function GetWeekNbr($aDate,$aSunStart=true) {
    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        
     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
    21502254    // Is year a leap year?
    21512255    function IsLeap($aYear) {
    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;
     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;
    21582262    }
    21592263
    21602264    // Get current year
    21612265    function GetYear($aDate) {
    2162         return 0+Date("Y",$aDate);
    2163     }
    2164        
     2266        return 0+Date("Y",$aDate);
     2267    }
     2268
    21652269    // Return number of days in a year
    21662270    function GetNumDaysInMonth($aMonth,$aYear) {
    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        
     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
    21752279    // Get day in month
    21762280    function GetMonthDayNbr($aDate) {
    2177         return 0+strftime("%d",$aDate);
     2281        return 0+strftime("%d",$aDate);
    21782282    }
    21792283
    21802284    // Get day in year
    21812285    function GetYearDayNbr($aDate) {
    2182         return 0+strftime("%j",$aDate);
    2183     }
    2184        
     2286        return 0+strftime("%j",$aDate);
     2287    }
     2288
    21852289    // Get month number
    21862290    function GetMonthNbr($aDate) {
    2187         return 0+strftime("%m",$aDate);
    2188     }
    2189        
    2190     // Translate a date to screen coordinates   (horizontal scale)
     2291        return 0+strftime("%m",$aDate);
     2292    }
     2293
     2294    // Translate a date to screen coordinates (horizontal scale)
    21912295    function TranslateDate($aDate) {
    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        
     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
    22332341    // What is the vertical spacing?
    22342342    function GetVertSpacing() {
    2235         return $this->iVertSpacing;
    2236     }
    2237                                        
     2343        return $this->iVertSpacing;
     2344    }
     2345
    22382346    // Convert a date to timestamp
    22392347    function NormalizeDate($aDate) {
    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    
     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
    22572365    // Convert a time string to minutes
    22582366
    22592367    function TimeToMinutes($aTimeString) {
    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)                       
     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)
    22762384    function StrokeMinutes($aYCoord,$getHeight=false) {
    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 ) {
     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 ) {
    22972405                JpGraphError::RaiseL(6018,$minint);
    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)                       
     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)
    23732479    function StrokeHours($aYCoord,$getHeight=false) {
    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 ) {
     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 ) {
    23932499                JpGraphError::RaiseL(6020,$tmp);
    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)                       
     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)
    24612567    function StrokeDays($aYCoord,$getHeight=false) {
    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        
     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
    25792685    // Stroke week header and grid
    25802686    function StrokeWeeks($aYCoord,$getHeight=false) {
    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        
     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
    26552762    // Format the mont scale header string
    26562763    function GetMonthLabel($aMonthNbr,$year) {
    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        
     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
    26852792    // Stroke month scale and gridlines
    26862793    function StrokeMonths($aYCoord,$getHeight=false) {
    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;
     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;
    27502857    }
    27512858
    27522859    // Stroke year scale and gridlines
    27532860    function StrokeYears($aYCoord,$getHeight=false) {
    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        
     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
    28112918    // Stroke table title (upper left corner)
    28122919    function StrokeTableHeaders($aYBottom) {
    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         }
     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        }
    28592966    }
    28602967
    28612968    // Main entry point to stroke scale
    28622969    function Stroke() {
    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     }   
     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    }
    29053014}
    29063015
     
    29173026    public $iConstrainArrowType;
    29183027
    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;
     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;
    29273036    }
    29283037}
     
    29363045    public $title,$caption;
    29373046    public $csimarea='',$csimtarget='',$csimwintarget='',$csimalt='';
    2938     public $constraints = array();   
     3047    public $constraints = array();
    29393048    public $iCaptionMargin=5;
    29403049    public $iConstrainPos=array();
    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();
     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();
    29493058    }
    29503059
    29513060    function GetCSIMArea() {
    2952         return $this->csimarea;
     3061        return $this->csimarea;
    29533062    }
    29543063
    29553064    function SetCSIMTarget($aTarget,$aAlt='',$aWinTarget='') {
    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         }
     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        }
    29663075
    29673076        $this->csimtarget=$aTarget;
     
    29693078        $this->csimalt=$aAlt;
    29703079    }
    2971    
     3080
    29723081    function SetCSIMAlt($aAlt) {
    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         }
     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        }
    29783087        $this->csimalt=$aAlt;
    29793088    }
    29803089
    29813090    function SetConstrain($aRow,$aType,$aColor='black',$aArrowSize=ARROW_S2,$aArrowType=ARROWT_SOLID) {
    2982         $this->constraints[] = new GanttConstraint($aRow, $aType, $aColor, $aArrowSize, $aArrowType);
     3091        $this->constraints[] = new GanttConstraint($aRow, $aType, $aColor, $aArrowSize, $aArrowType);
    29833092    }
    29843093
    29853094    function SetConstrainPos($xt,$yt,$xb,$yb) {
    2986         $this->iConstrainPos = array($xt,$yt,$xb,$yb);
    2987     }
    2988 
    2989     /*
    2990     function GetConstrain() {
    2991         return array($this->iConstrainRow,$this->iConstrainType);
    2992     }
    2993     */
    2994        
     3095        $this->iConstrainPos = array($xt,$yt,$xb,$yb);
     3096    }
     3097
    29953098    function GetMinDate() {
    2996         return $this->iStart;
     3099        return $this->iStart;
    29973100    }
    29983101
    29993102    function GetMaxDate() {
    3000         return $this->iStart;
    3001     }
    3002        
     3103        return $this->iStart;
     3104    }
     3105
    30033106    function SetCaptionMargin($aMarg) {
    3004         $this->iCaptionMargin=$aMarg;
     3107        $this->iCaptionMargin=$aMarg;
    30053108    }
    30063109
    30073110    function GetAbsHeight($aImg) {
    3008         return 0;
    3009     }
    3010        
     3111        return 0;
     3112    }
     3113
    30113114    function GetLineNbr() {
    3012         return $this->iVPos;
     3115        return $this->iVPos;
    30133116    }
    30143117
    30153118    function SetLabelLeftMargin($aOff) {
    3016         $this->iLabelLeftMargin=$aOff;
    3017     }           
     3119        $this->iLabelLeftMargin=$aOff;
     3120    }
    30183121
    30193122    function StrokeActInfo($aImg,$aScale,$aYPos) {
    3020         $cols=array();
    3021         $aScale->actinfo->GetColStart($aImg,$cols,true);
    3022         $this->title->Stroke($aImg,$cols,$aYPos);               
     3123        $cols=array();
     3124        $aScale->actinfo->GetColStart($aImg,$cols,true);
     3125        $this->title->Stroke($aImg,$cols,$aYPos);
    30233126    }
    30243127}
     
    30263129//===================================================
    30273130// CLASS Progress
    3028 // Holds parameters for the progress indicator 
     3131// Holds parameters for the progress indicator
    30293132// displyed within a bar
    30303133//===================================================
     
    30333136    public $iPattern=GANTT_SOLID;
    30343137    public $iColor="black", $iFillColor='black';
    3035     public $iDensity=98, $iHeight=0.65; 
    3036        
     3138    public $iDensity=98, $iHeight=0.65;
     3139
    30373140    function Set($aProg) {
    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;
     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;
    30483152    }
    30493153
    30503154    function SetFillColor($aColor) {
    3051         $this->iFillColor = $aColor;
    3052     }
    3053        
     3155        $this->iFillColor = $aColor;
     3156    }
     3157
    30543158    function SetHeight($aHeight) {
    3055         $this->iHeight = $aHeight;
     3159        $this->iHeight = $aHeight;
    30563160    }
    30573161}
     
    30713175    private $iStart=0; // 0=from left margin, 1=just along header
    30723176
    3073     function HorizontalGridLine() {
    3074         $this->line = new LineProperty();
    3075         $this->line->SetColor('gray@0.4');
    3076         $this->line->SetStyle('dashed');
    3077     }
    3078    
     3177    function __construct() {
     3178        $this->line = new LineProperty();
     3179        $this->line->SetColor('gray@0.4');
     3180        $this->line->SetStyle('dashed');
     3181    }
     3182
    30793183    function Show($aShow=true) {
    3080         $this->iShow = $aShow;
     3184        $this->iShow = $aShow;
    30813185    }
    30823186
    30833187    function SetRowFillColor($aColor1,$aColor2='') {
    3084         $this->iRowColor1 = $aColor1;
    3085         $this->iRowColor2 = $aColor2;
     3188        $this->iRowColor1 = $aColor1;
     3189        $this->iRowColor2 = $aColor2;
    30863190    }
    30873191
    30883192    function SetStart($aStart) {
    3089         $this->iStart = $aStart;
     3193        $this->iStart = $aStart;
    30903194    }
    30913195
    30923196    function Stroke($aImg,$aScale) {
    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);
     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);
    31373241    }
    31383242}
     
    31513255    private $iShadow=false,$iShadowColor="darkgray",$iShadowWidth=1,$iShadowFrame="black";
    31523256    private $iPattern=GANTT_RDIAG,$iPatternColor="blue",$iPatternDensity=95;
    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       
     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
    31833291    function SetShadow($aShadow=true,$aColor="gray") {
    3184         $this->iShadow=$aShadow;
    3185         $this->iShadowColor=$aColor;
    3186     }
    3187    
     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
    31883302    function GetMaxDate() {
    3189         return $this->iEnd;
    3190     }
    3191        
     3303        return $this->iEnd;
     3304    }
     3305
    31923306    function SetHeight($aHeight) {
    3193         $this->iHeightFactor = $aHeight;
     3307        $this->iHeightFactor = $aHeight;
    31943308    }
    31953309
    31963310    function SetColor($aColor) {
    3197         $this->iFrameColor = $aColor;
     3311        $this->iFrameColor = $aColor;
    31983312    }
    31993313
    32003314    function SetFillColor($aColor) {
    3201         $this->iFillColor = $aColor;
     3315        $this->iFillColor = $aColor;
    32023316    }
    32033317
    32043318    function GetAbsHeight($aImg) {
    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;
     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;
    32233337    }
    32243338
    32253339    function Stroke($aImg,$aScale) {
    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         }
     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        }
    33843510    }
    33853511}
     
    33913517class MileStone extends GanttPlotObject {
    33923518    public $mark;
    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        
     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
    34153541    function GetAbsHeight($aImg) {
    3416         return max($this->title->GetHeight($aImg),$this->mark->GetWidth());
    3417     }
    3418                
     3542        return max($this->title->GetHeight($aImg),$this->mark->GetWidth());
     3543    }
     3544
    34193545    function Stroke($aImg,$aScale) {
    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();
     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();
    34773603    }
    34783604}
     
    34853611
    34863612class TextPropertyBelow extends TextProperty {
    3487     function TextPropertyBelow($aTxt='') {
    3488         parent::TextProperty($aTxt);
     3613    function __construct($aTxt='') {
     3614        parent::__construct($aTxt);
    34893615    }
    34903616
    34913617    function GetColWidth($aImg,$aMargin=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);
     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);
    34953621    }
    34963622}
     
    34983624class GanttVLine extends GanttPlotObject {
    34993625
    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       
     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    }
    35173651
    35183652    function SetDayOffset($aOff=0.5) {
    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        
     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
    35253660    function SetTitleMargin($aMarg) {
    3526         $this->title_margin = $aMarg;
    3527     }
    3528        
     3661        $this->title_margin = $aMarg;
     3662    }
     3663
     3664    function SetWeight($aWeight) {
     3665        $this->iLine->SetWeight($aWeight);
     3666    }
     3667
    35293668    function Stroke($aImg,$aScale) {
    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     }   
     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    }
    35423694}
    35433695
    35443696//===================================================
    35453697// CLASS LinkArrow
    3546 // Handles the drawing of a an arrow 
     3698// Handles the drawing of a an arrow
    35473699//===================================================
    35483700class LinkArrow {
    35493701    private $ix,$iy;
    35503702    private $isizespec = array(
    3551         array(2,3),array(3,5),array(3,8),array(6,15),array(8,22));
     3703    array(2,3),array(3,5),array(3,8),array(6,15),array(8,22));
    35523704    private $iDirection=ARROW_DOWN,$iType=ARROWT_SOLID,$iSize=ARROW_S2;
    35533705    private $iColor='black';
    35543706
    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    
     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
    35633715    function SetColor($aColor) {
    3564         $this->iColor = $aColor;
     3716        $this->iColor = $aColor;
    35653717    }
    35663718
    35673719    function SetSize($aSize) {
    3568         $this->iSize = $aSize;
     3720        $this->iSize = $aSize;
    35693721    }
    35703722
    35713723    function SetType($aType) {
    3572         $this->iType = $aType;
     3724        $this->iType = $aType;
    35733725    }
    35743726
    35753727    function Stroke($aImg) {
    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         }
     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        }
    36123764    }
    36133765}
     
    36243776    private $iArrowSize=ARROW_S2,$iArrowType=ARROWT_SOLID;
    36253777
    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;
     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;
    36313783    }
    36323784
    36333785    function SetPos($x1,$y1,$x2,$y2) {
    3634         $this->ix1 = $x1;
    3635         $this->ix2 = $x2;
    3636         $this->iy1 = $y1;
    3637         $this->iy2 = $y2;
     3786        $this->ix1 = $x1;
     3787        $this->ix2 = $x2;
     3788        $this->iy1 = $y1;
     3789        $this->iy2 = $y2;
    36383790    }
    36393791
    36403792    function SetPath($aPath) {
    3641         $this->iPathType = $aPath;
     3793        $this->iPathType = $aPath;
    36423794    }
    36433795
    36443796    function SetColor($aColor) {
    3645         $this->iColor = $aColor;
     3797        $this->iColor = $aColor;
    36463798    }
    36473799
    36483800    function SetArrow($aSize,$aType=ARROWT_SOLID) {
    3649         $this->iArrowSize = $aSize;
    3650         $this->iArrowType = $aType;
    3651     }
    3652    
     3801        $this->iArrowSize = $aSize;
     3802        $this->iArrowType = $aType;
     3803    }
     3804
    36533805    function SetWeight($aWeight) {
    3654         $this->iWeight = $aWeight;
     3806        $this->iWeight = $aWeight;
    36553807    }
    36563808
    36573809    function 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);
     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);
    37993951    }
    38003952}
  • trunk/client/modules/Elezioni/grafici/jpgraph_gb2312.php

    r267 r284  
    11<?php
    22//=======================================================================
    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 $
     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 $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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,
     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 );
    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;
    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;
     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;
    15481525    }
    15491526
    1550 } // END Class
     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
    15511551
    15521552?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_gradient.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1761 2009-08-01 08:31:28Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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 Gradient(&$img) {
    36         $this->img = $img;
     33    //---------------
     34    // CONSTRUCTOR
     35    function __construct(&$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         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         }
     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        }
    323328    }
    324329
     
    329334    // of a mountain)
    330335    function FilledFlatPolygon($pts,$from_color,$to_color) {
    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         }
     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        }
    386393    }
    387394
    388 //---------------
    389 // PRIVATE METHODS     
     395    //---------------
     396    // PRIVATE METHODS
    390397    // Add to the image color map the necessary colors to do the transition
    391398    // between the two colors using $numcolors intermediate colors
    392399    function GetColArray($from_color,$to_color,$arr_size,&$colors,$numcols=100) {
    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     }   
     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    }
    421432} // Class
    422433
  • trunk/client/modules/Elezioni/grafici/jpgraph_iconplot.php

    r267 r284  
    11<?php
    22//=======================================================================
    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 $
     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 $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. All rights reserved.
    99//========================================================================
    1010
     
    2525
    2626
    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 ;
     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 ;
    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,$ayscale) {
    115         $this->StrokeWithScale($aImg,$axscale,$ayscale);
     114    function Stroke($aImg,$axscale=null,$ayscale=null) {
     115        $this->StrokeWithScale($aImg,$axscale,$ayscale);
    116116    }
    117117
    118118    function StrokeWithScale($aImg,$axscale,$ayscale) {
    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         }
     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        }
    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);
    157        
    158         if( $aReturnWidthHeight ) {
    159             return array(round($iconw*$this->iScale),round($iconh*$this->iScale));
    160         }
     155        $iconw = imagesx($gdimg);
     156        $iconh = imagesy($gdimg);
    161157
    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         }
     158        if( $aReturnWidthHeight ) {
     159            return array(round($iconw*$this->iScale),round($iconh*$this->iScale));
     160        }
    173161
    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);
     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        }
    182173
    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);
     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);
    187187    }
    188188}
  • trunk/client/modules/Elezioni/grafici/jpgraph_imgtrans.php

    r267 r284  
    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 781 2006-10-08 08:07:47Z 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 1106 2009-02-22 20:16:35Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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 ImgTrans($aGdImg) {
    19         // Constructor
    20         $this->gdImg = $aGdImg;
    21     }
    22 
    23     // --------------------------------------------------------------------
    24     // _TransVert3D() and _TransHor3D() are helper methods to 
    25     // Skew3D(). 
     18    function __construct($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

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
     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 $
    77//
    8 // Copyright 2006 (c) Aditus Consulting. All rights reserved.
     8// Copyright 2006 (c) Asial Corporation. 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 //
    2111//========================================================================
    2212
    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
    51 define('LEDC_RED', 0);
    52 define('LEDC_GREEN', 1);
    53 define('LEDC_BLUE', 2);
    54 define('LEDC_YELLOW', 3);
    55 define('LEDC_GRAY', 4);
    56 define('LEDC_CHOCOLATE', 5);
    57 define('LEDC_PERU', 6);
    58 define('LEDC_GOLDENROD', 7);
    59 define('LEDC_KHAKI', 8);
    60 define('LEDC_OLIVE', 9);
    61 define('LEDC_LIMEGREEN', 10);
    62 define('LEDC_FORESTGREEN', 11);
    63 define('LEDC_TEAL', 12);
    64 define('LEDC_STEELBLUE', 13);
    65 define('LEDC_NAVY', 14);
    66 define('LEDC_INVERTGRAY', 15);
    67 // ! It correlate with two-dimensional array $iColorSchema
     13// Constants for color schema
     14DEFINE('LEDC_RED', 0);
     15DEFINE('LEDC_GREEN', 1);
     16DEFINE('LEDC_BLUE', 2);
     17DEFINE('LEDC_YELLOW', 3);
     18DEFINE('LEDC_GRAY', 4);
     19DEFINE('LEDC_CHOCOLATE', 5);
     20DEFINE('LEDC_PERU', 6);
     21DEFINE('LEDC_GOLDENROD', 7);
     22DEFINE('LEDC_KHAKI', 8);
     23DEFINE('LEDC_OLIVE', 9);
     24DEFINE('LEDC_LIMEGREEN', 10);
     25DEFINE('LEDC_FORESTGREEN', 11);
     26DEFINE('LEDC_TEAL', 12);
     27DEFINE('LEDC_STEELBLUE', 13);
     28DEFINE('LEDC_NAVY', 14);
     29DEFINE('LEDC_INVERTGRAY', 15);
     30
     31// Check that mb_strlen() is available
     32if( ! 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}
    6837
    6938//========================================================================
    7039// CLASS DigitalLED74
    71 // Description: 
     40// Description:
    7241// Construct a number as an image that looks like LED numbers in a
    7342// 7x4 digital matrix
     
    7746    private $iLED_X = 4, $iLED_Y=7,
    7847
    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;
    228     }
    229    
    230     function SetSupersampling($aSuperSampling = 2)      {
    231         $this->iSuperSampling = $aSuperSampling;
    232     }
    233 
    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;
    281     }
     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;
     212    }
     213
     214    function SetSupersampling($aSuperSampling = 2) {
     215        $this->iSuperSampling = $aSuperSampling;
     216    }
     217
     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;
     265    }
     266
     267
     268    function Stroke($aValStr, $aColor = 0, $aFileName = '') {
     269        $this->StrokeNumber($aValStr, $aColor, $aFileName);
     270    }
     271
    282272
    283273    function StrokeNumber($aValStr, $aColor = 0, $aFileName = '') {
    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         }
     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        }
    318309    }
    319310}
  • trunk/client/modules/Elezioni/grafici/jpgraph_legend.inc.php

    r267 r284  
    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 1048 2008-08-01 19:56:46Z 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 1926 2010-01-11 16:33:07Z ljp $
    99//
    10 // Copyright (c) Aditus Consulting. All rights reserved.
     10// Copyright (c) Asial Corporation. 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     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';
     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';
    2829    private $mark_abs_hsize=_DEFAULT_LPM_SIZE,$mark_abs_vsize=_DEFAULT_LPM_SIZE;
    29     private $xmargin=10,$ymargin=3,$shadow_width=2;
    30     private $xlmargin=2, $ylmargin='';
     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   
    3137    private $xpos=0.05, $ypos=0.15, $xabspos=-1, $yabspos=-1;
    3238    private $halign="right", $valign="top";
    33     private $font_family=FF_FONT1,$font_style=FS_NORMAL,$font_size=12;
    3439    private $font_color='black';
    3540    private $hide=false,$layout_n=1;
     
    3742    private $csimareas='';
    3843    private $reverse = false ;
    39 
    40 //---------------
    41 // CONSTRUCTOR
    42     function Legend() {
    43         // Empty
    44     }
    45 //---------------
    46 // PUBLIC METHODS       
     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
    4753    function Hide($aHide=true) {
    48         $this->hide=$aHide;
    49     }
    50        
     54        $this->hide=$aHide;
     55    }
     56
    5157    function SetHColMargin($aXMarg) {
    52         $this->xmargin = $aXMarg;
     58        $this->xmargin = $aXMarg;
    5359    }
    5460
    5561    function SetVColMargin($aSpacing) {
    56         $this->ymargin = $aSpacing ;
     62        $this->ylinespacing = $aSpacing ;
    5763    }
    5864
    5965    function SetLeftMargin($aXMarg) {
    60         $this->xlmargin = $aXMarg;
     66        $this->xlmargin = $aXMarg;
    6167    }
    6268
    6369    // Synonym
    6470    function SetLineSpacing($aSpacing) {
    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;
     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;
    7683    }
    7784
    7885    function SetMarkAbsSize($aSize) {
    79         $this->mark_abs_vsize = $aSize ;
    80         $this->mark_abs_hsize = $aSize ;
     86        $this->mark_abs_vsize = $aSize ;
     87        $this->mark_abs_hsize = $aSize ;
    8188    }
    8289
    8390    function SetMarkAbsVSize($aSize) {
    84         $this->mark_abs_vsize = $aSize ;
     91        $this->mark_abs_vsize = $aSize ;
    8592    }
    8693
    8794    function SetMarkAbsHSize($aSize) {
    88         $this->mark_abs_hsize = $aSize ;
     95        $this->mark_abs_hsize = $aSize ;
    8996    }
    9097
    9198    function SetLineWeight($aWeight) {
    92         $this->weight = $aWeight;
     99        $this->weight = $aWeight;
    93100    }
    94101
    95102    function SetFrameWeight($aWeight) {
    96         $this->frameweight = $aWeight;
    97     }
    98        
     103        $this->frameweight = $aWeight;
     104    }
     105
    99106    function SetLayout($aDirection=LEGEND_VERT) {
    100         $this->layout_n = $aDirection==LEGEND_VERT ? 1 : 99 ;
    101     }
    102        
     107        $this->layout_n = $aDirection==LEGEND_VERT ? 1 : 99 ;
     108    }
     109
    103110    function SetColumns($aCols) {
    104         $this->layout_n = $aCols ;
     111        $this->layout_n = $aCols ;
    105112    }
    106113
    107114    function SetReverse($f=true) {
    108         $this->reverse = $f ;
     115        $this->reverse = $f ;
    109116    }
    110117
    111118    // Set color on frame around box
    112119    function SetColor($aFontColor,$aColor='black') {
    113         $this->font_color=$aFontColor;
    114         $this->color=$aColor;
    115     }
    116        
     120        $this->font_color=$aFontColor;
     121        $this->color=$aColor;
     122    }
     123
    117124    function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) {
    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;
     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;
    142149    }
    143150
    144151    function SetFillColor($aColor) {
    145         $this->fill_color=$aColor;
    146     }
    147        
     152        $this->fill_color=$aColor;
     153    }
     154
     155    function Clear() {
     156        $this->txtcol = array();
     157    }
     158
    148159    function Add($aTxt,$aColor,$aPlotmark='',$aLinestyle=0,$csimtarget='',$csimalt='',$csimwintarget='') {
    149         $this->txtcol[]=array($aTxt,$aColor,$aPlotmark,$aLinestyle,$csimtarget,$csimalt,$csimwintarget);
     160        $this->txtcol[]=array($aTxt,$aColor,$aPlotmark,$aLinestyle,$csimtarget,$csimalt,$csimwintarget);
    150161    }
    151162
    152163    function GetCSIMAreas() {
    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
     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
    172193        // to size the legend box.
    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         }       
     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        }
    391491    }
    392492} // Class
    393        
     493
    394494?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_line.php

    r267 r284  
    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 981 2008-03-24 11:51:12Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1921 2009-12-11 11:46:39Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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 ;
     32    protected $fillFromMin = false, $fillFromMax = false;
    3333    protected $fillgrad=false,$fillgrad_fromcolor='navy',$fillgrad_tocolor='silver',$fillgrad_numcolors=100;
    3434    protected $iFastStroke=false;
    3535
    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        
     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
    5051    function SetBarCenter($aFlag=true) {
    51         $this->barcenter=$aFlag;
     52        $this->barcenter=$aFlag;
    5253    }
    5354
    5455    function SetStyle($aStyle) {
    55         $this->line_style=$aStyle;
    56     }
    57        
     56        $this->line_style=$aStyle;
     57    }
     58
    5859    function SetStepStyle($aFlag=true) {
    59         $this->step_style = $aFlag;
    60     }
    61        
     60        $this->step_style = $aFlag;
     61    }
     62
    6263    function SetColor($aColor) {
    63         parent::SetColor($aColor);
    64     }
    65        
     64        parent::SetColor($aColor);
     65    }
     66
    6667    function SetFillFromYMin($f=true) {
    67         $this->fillFromMin = $f ;
    68     }
    69    
     68        $this->fillFromMin = $f ;
     69    }
     70
     71    function SetFillFromYMax($f=true) {
     72        $this->fillFromMax = $f ;
     73    }
     74
    7075    function SetFillColor($aColor,$aFilled=true) {
    71         $this->fill_color=$aColor;
    72         $this->filled=$aFilled;
     76        //$this->color = $aColor;
     77        $this->fill_color=$aColor;
     78        $this->filled=$aFilled;
    7379    }
    7480
    7581    function SetFillGradient($aFromColor,$aToColor,$aNumColors=100,$aFilled=true) {
    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        
     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
    8389    function Legend($graph) {
    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         }       
     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        }
    101107    }
    102108
    103109    function AddArea($aMin=0,$aMax=0,$aFilled=LP_AREA_NOT_FILLED,$aColor="gray9",$aBorder=LP_AREA_BORDER) {
    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        
     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
    113119    // Gets called before any axis are stroked
    114120    function PreStrokeAdjust($graph) {
    115121
    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    
     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
    134139    function SetFastStroke($aFlg=true) {
    135         $this->iFastStroke = $aFlg;
     140        $this->iFastStroke = $aFlg;
    136141    }
    137142
    138143    function FastStroke($img,$xscale,$yscale,$aStartPoint=0,$exist_x=true) {
    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        
     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
    173184    function Stroke($img,$xscale,$yscale) {
    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         }
     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        }
    415462    }
    416463} // Class
     
    419466//===================================================
    420467// CLASS AccLinePlot
    421 // Description: 
     468// Description:
    422469//===================================================
    423470class AccLinePlot extends Plot {
    424471    protected $plots=null,$nbrplots=0;
    425472    private $iStartEndZero=true;
    426 //---------------
    427 // CONSTRUCTOR
    428     function AccLinePlot($plots) {
     473    //---------------
     474    // CONSTRUCTOR
     475    function __construct($plots) {
    429476        $this->plots = $plots;
    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       
     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
    447494    function Legend($graph) {
    448         foreach( $this->plots as $p )
    449             $p->DoLegend($graph);
    450     }
    451        
     495        foreach( $this->plots as $p ) {
     496            $p->DoLegend($graph);
     497        }
     498    }
     499
    452500    function Max() {
    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     }   
     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    }
    477525
    478526    function Min() {
    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);
     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);
    503551    }
    504552
     
    506554    function PreStrokeAdjust($graph) {
    507555
    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        
     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
    526574    }
    527575
    528576    function SetInterpolateMode($aIntMode) {
    529         $this->iStartEndZero=$aIntMode;
     577        $this->iStartEndZero=$aIntMode;
    530578    }
    531579
     
    535583    function LineInterpolate(&$aData) {
    536584
    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 
     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    }
    596645
    597646    // To avoid duplicate of line drawing code here we just
     
    602651    // since this method would have a side effect.
    603652    function Stroke($img,$xscale,$yscale) {
    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         }
     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        }
    627677    }
    628678} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_log.php

    r267 r284  
    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 957 2007-12-01 14:00:29Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1106 2009-02-22 20:16:35Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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 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       
     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
    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             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);
     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);
    4950    }
    5051
    5152    // Relative translate (don't include offset) usefull when we just want
    52     // to know the relative position (in pixels) on the axis   
     53    // to know the relative position (in pixels) on the axis
    5354    function RelTranslate($a) {
    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                
     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
    6569    // Use bcpow() for increased precision
    6670    function GetMinVal() {
    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        
     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
    7379    function GetMaxVal() {
    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        
     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
    8088    // Logarithmic autoscaling is much simplier since we just
    8189    // set the min and max to logs of the min and max values.
     
    8492    // signature as the linear counterpart.
    8593    function AutoScale($img,$min,$max,$maxsteps,$majend=true) {
    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     
     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
    115123} // Class
    116124
    117125//===================================================
    118126// CLASS LogTicks
    119 // Description: 
     127// Description:
    120128//===================================================
    121129class LogTicks extends Ticks{
    122130    private $label_logtype=LOGLABELS_MAGNITUDE;
    123131    private $ticklabels_pos = array();
    124 //---------------
    125 // CONSTRUCTOR
    126     function LogTicks() {
    127     }
    128 //---------------
    129 // PUBLIC METHODS       
     132    //---------------
     133    // CONSTRUCTOR
     134    function __construct() {
     135    }
     136    //---------------
     137    // PUBLIC METHODS
    130138    function IsSpecified() {
    131         return true;
     139        return true;
    132140    }
    133141
    134142    function SetLabelLogType($aType) {
    135         $this->label_logtype = $aType;
    136     }
    137        
     143        $this->label_logtype = $aType;
     144    }
     145
    138146    // For log scale it's meaningless to speak about a major step
    139147    // We just return -1 to make the framework happy (specifically
    140148    // StrokeLabels() )
    141149    function GetMajor() {
    142         return -1;
     150        return -1;
    143151    }
    144152
    145153    function SetTextLabelStart($aStart) {
    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.');
     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.');
    148156    }
    149157
    150158    function SetXLabelOffset($dummy) {
    151         // For log scales we dont care about XLabel offset
     159        // For log scales we dont care about XLabel offset
    152160    }
    153161
     
    157165    // absolute x-position.
    158166    function Stroke($img,$scale,$pos) {
    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;
     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;
    280302    }
    281303} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_mgraph.php

    r267 r284  
    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 1012 2008-06-23 15:02:15Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1770 2009-08-17 06:10:22Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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;
    1719
    1820    protected $img=NULL;
    1921    protected $iCnt=0,$iGraphs = array(); // image_handle, x, y, fx, fy, sizex, sizey
    2022    protected $iFillColor='white', $iCurrentColor=0;
    21     protected $lm=0,$rm=0,$tm=0,$bm=0;
     23    protected $lm=4,$rm=4,$tm=4,$bm=4;
    2224    protected $iDoFrame = FALSE, $iFrameColor = 'black', $iFrameWeight = 1;
    2325    protected $iLineWeight = 1;
    2426    protected $expired=false;
    25     protected $img_format='png',$image_quality=75;
     27    protected $cache=null,$cache_name = '',$inline=true;
     28    protected $image_format='png',$image_quality=75;
    2629    protected $iWidth=NULL,$iHeight=NULL;
    2730    protected $background_image='',$background_image_center=true,
    28         $backround_image_format='',$background_image_mix=100,
    29         $background_image_y=NULL, $background_image_x=NULL;
     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
    3036
    3137    // Create a new instane of the combined graph
    32     function MGraph($aWidth=NULL,$aHeight=NULL) {
    33         $this->iWidth = $aWidth;
    34         $this->iHeight = $aHeight;
     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
    3575    }
    3676
    3777    // Specify background fill color for the combined graph
    3878    function SetFillColor($aColor) {
    39         $this->iFillColor = $aColor;
     79        $this->iFillColor = $aColor;
    4080    }
    4181
    4282    // Add a frame around the combined graph
    4383    function SetFrame($aFlg,$aColor='black',$aWeight=1) {
    44         $this->iDoFrame = $aFlg;
    45         $this->iFrameColor = $aColor;
    46         $this->iFrameWeight = $aWeight;
    47     }
    48 
    49     // Specify a background image blend   
     84        $this->iDoFrame = $aFlg;
     85        $this->iFrameColor = $aColor;
     86        $this->iFrameWeight = $aWeight;
     87    }
     88
     89    // Specify a background image blend
    5090    function SetBackgroundImageMix($aMix) {
    51         $this->background_image_mix = $aMix ;
     91        $this->background_image_mix = $aMix ;
    5292    }
    5393
    5494    // Specify a background image
    5595    function SetBackgroundImage($aFileName,$aCenter_aX=NULL,$aY=NULL) {
    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     }   
     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    }
    132128
    133129    function _strokeBackgroundImage() {
    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);
     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);
    222162    }
    223163
    224164    function AddMix($aGraph,$x=0,$y=0,$mix=100,$fx=0,$fy=0,$w=0,$h=0) {
    225         $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h,$mix);
    226     }
    227    
     165        $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h,$mix);
     166    }
     167
    228168    function Add($aGraph,$x=0,$y=0,$fx=0,$fy=0,$w=0,$h=0) {
    229         $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h);
     169        $this->_gdImgHandle($aGraph->Stroke( _IMG_HANDLER),$x,$y,$fx=0,$fy=0,$w,$h);
    230170    }
    231171
    232172    function _gdImgHandle($agdCanvas,$x,$y,$fx=0,$fy=0,$w=0,$h=0,$mix=100) {
    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);
     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);
    241185    }
    242186
    243187    function SetMargin($lm,$rm,$tm,$bm) {
    244         $this->lm = $lm;
    245         $this->rm = $rm;
    246         $this->tm = $tm;
    247         $this->bm = $bm;
     188        $this->lm = $lm;
     189        $this->rm = $rm;
     190        $this->tm = $tm;
     191        $this->bm = $bm;
    248192    }
    249193
    250194    function SetExpired($aFlg=true) {
    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>
    266 HTTP 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");
     195        $this->expired = $aFlg;
    279196    }
    280197
    281198    function SetImgFormat($aFormat,$aQuality=75) {
    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.");
     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        }
    335269    }
    336270
    337271    function Stroke($aFileName='') {
    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         }
     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        }
    389340    }
    390341}
    391342
     343// EOF
     344
    392345?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_pie.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1926 2010-01-11 16:33:07Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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;
    2629    protected $radius=0.3;
    2730    protected $explode_radius=array(),$explode_all=false,$explode_r=20;
    2831    protected $labels=null, $legends=null;
    2932    protected $csimtargets=null,$csimwintargets=null;  // Array of targets for CSIM
    30     protected $csimareas='';            // Generated CSIM text 
    31     protected $csimalts=null;           // ALT tags for corresponding target
     33    protected $csimareas='';  // Generated CSIM text
     34    protected $csimalts=null;  // ALT tags for corresponding target
    3235    protected $data=null;
    3336    public $title;
     
    3639    protected $legend_margin=6,$show_labels=true;
    3740    protected $themearr = array(
    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";
     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));
    4345    protected $setslicecolors=array();
    4446    protected $labeltype=0; // Default to percentage
     
    5456    protected $iGuideLineCurve = false,$iGuideVFactor=1.4,$iGuideLineRFactor=0.8;
    5557    protected $la = array(); // Holds the exact angle for each label
    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       
     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
    7173    function SetCenter($x,$y=0.5) {
    72         $this->posx = $x;
    73         $this->posy = $y;
     74        $this->posx = $x;
     75        $this->posy = $y;
    7476    }
    7577
    7678    // Enable guideline and set drwaing policy
    7779    function SetGuideLines($aFlg=true,$aCurved=true,$aAlways=false) {
    78         $this->guideline->Show($aFlg);
    79         $this->iShowGuideLineForSingle = $aAlways;
    80         $this->iGuideLineCurve = $aCurved;
     80        $this->guideline->Show($aFlg);
     81        $this->iShowGuideLineForSingle = $aAlways;
     82        $this->iGuideLineCurve = $aCurved;
    8183    }
    8284
    8385    // Adjuste the distance between labels and labels and pie
    8486    function SetGuideLinesAdjust($aVFactor,$aRFactor=0.8) {
    85         $this->iGuideVFactor=$aVFactor;
    86         $this->iGuideLineRFactor=$aRFactor;
     87        $this->iGuideVFactor=$aVFactor;
     88        $this->iGuideLineRFactor=$aRFactor;
    8789    }
    8890
    8991    function SetColor($aColor) {
    90         $this->color = $aColor;
    91     }
    92        
     92        $this->color = $aColor;
     93    }
     94
    9395    function SetSliceColors($aColors) {
    94         $this->setslicecolors = $aColors;
    95     }
    96        
     96        $this->setslicecolors = $aColors;
     97    }
     98
    9799    function SetShadow($aColor='darkgray',$aDropWidth=4) {
    98         $this->ishadowcolor = $aColor;
    99         $this->ishadowdrop = $aDropWidth;
     100        $this->ishadowcolor = $aColor;
     101        $this->ishadowdrop = $aDropWidth;
    100102    }
    101103
    102104    function SetCSIMTargets($aTargets,$aAlts='',$aWinTargets='') {
    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        
     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
    110112    function GetCSIMareas() {
    111         return $this->csimareas;
    112     }
    113 
    114     function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { 
     113        return $this->csimareas;
     114    }
     115
     116    function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {
    115117        //Slice number, ellipse centre (x,y), height, width, start angle, end angle
    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        
     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
    179181    function SetTheme($aTheme) {
    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        
     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
    186193    function ExplodeSlice($e,$radius=20) {
    187         if( ! is_integer($e) )
    188             JpGraphError::RaiseL(15002);//('Argument to PiePlot::ExplodeSlice() must be an integer');
    189         $this->explode_radius[$e]=$radius;
     194        if( ! is_integer($e) )
     195        JpGraphError::RaiseL(15002);//('Argument to PiePlot::ExplodeSlice() must be an integer');
     196        $this->explode_radius[$e]=$radius;
    190197    }
    191198
    192199    function ExplodeAll($radius=20) {
    193         $this->explode_all=true;
    194         $this->explode_r = $radius;
     200        $this->explode_all=true;
     201        $this->explode_r = $radius;
    195202    }
    196203
    197204    function Explode($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;
     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;
    203210    }
    204211
    205212    function SetStartAngle($aStart) {
    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        
     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
    217225    // Size in percentage
    218226    function SetSize($aSize) {
    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        
     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
    231234    // Set label arrays
    232235    function SetLegends($aLegend) {
    233         $this->legends = $aLegend;
    234     }
    235 
    236     // Set text labels for slices 
     236        $this->legends = $aLegend;
     237    }
     238
     239    // Set text labels for slices
    237240    function SetLabels($aLabels,$aLblPosAdj="auto") {
    238         $this->labels = array_reverse($aLabels);
    239         $this->ilabelposadj=$aLblPosAdj;
     241        $this->labels = array_reverse($aLabels);
     242        $this->ilabelposadj=$aLblPosAdj;
    240243    }
    241244
    242245    function SetLabelPos($aLblPosAdj) {
    243         $this->ilabelposadj=$aLblPosAdj;
    244     }
    245        
     246        $this->ilabelposadj=$aLblPosAdj;
     247    }
     248
    246249    // Should we display actual value or percentage?
    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. 
     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.
    255258    function SetValueType($aType) {
    256         $this->SetLabelType($aType);
     259        $this->SetLabelType($aType);
    257260    }
    258261
    259262    // Should the circle around a pie plot be displayed
    260263    function ShowBorder($exterior=true,$interior=true) {
    261         $this->pie_border = $exterior;
    262         $this->pie_interior_border = $interior;
    263     }
    264        
     264        $this->pie_border = $exterior;
     265        $this->pie_interior_border = $interior;
     266    }
     267
    265268    // Setup the legends
    266269    function Legend($graph) {
    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        
     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
    340345    // Adjust the rounded percetage value so that the sum of
    341346    // of the pie slices are always 100%
    342347    // Using the Hare/Niemeyer method
    343348    function AdjPercentage($aData,$aPrec=0) {
    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;
     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;
    387392    }
    388393
    389394
    390395    function Stroke($img,$aaoption=0) {
    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     
     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
    641659
    642660    function NormAngle($a) {
    643         while( $a < 0 ) $a += 2*M_PI;
    644         while( $a > 2*M_PI ) $a -= 2*M_PI;
    645         return $a;
     661        while( $a < 0 ) $a += 2*M_PI;
     662        while( $a > 2*M_PI ) $a -= 2*M_PI;
     663        return $a;
    646664    }
    647665
    648666    function Quadrant($a) {
    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;
     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;
    658676    }
    659677
    660678    function StrokeGuideLabels($img,$xc,$yc,$radius) {
    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         }
     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        }
    925943    }
    926944
    927945    function StrokeAllLabels($img,$xc,$yc,$radius) {
    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         }
     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        }
    944962    }
    945963
     
    947965    function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
    948966
    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     }   
     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    }
    10161038} // Class
    10171039
     
    10191041//===================================================
    10201042// CLASS PiePlotC
    1021 // Description: Same as a normal pie plot but with a 
     1043// Description: Same as a normal pie plot but with a
    10221044// filled circle in the center
    10231045//===================================================
    10241046class PiePlotC extends PiePlot {
    1025     private $imidsize=0.5;              // Fraction of total width
     1047    private $imidsize=0.5;  // Fraction of total width
    10261048    private $imidcolor='white';
    10271049    public $midtitle='';
    10281050    private $middlecsimtarget='',$middlecsimwintarget='',$middlecsimalt='';
    10291051
    1030     function PiePlotC($data,$aCenterTitle='') {
    1031         parent::PiePlot($data);
    1032         $this->midtitle = new Text();
    1033         $this->midtitle->ParagraphAlign('center');
     1052    function __construct($data,$aCenterTitle='') {
     1053        parent::__construct($data);
     1054        $this->midtitle = new Text();
     1055        $this->midtitle->ParagraphAlign('center');
    10341056    }
    10351057
    10361058    function SetMid($aTitle,$aColor='white',$aSize=0.5) {
    1037         $this->midtitle->Set($aTitle);
    1038 
    1039         $this->imidsize = $aSize ;
    1040         $this->imidcolor = $aColor ;
     1059        $this->midtitle->Set($aTitle);
     1060
     1061        $this->imidsize = $aSize ;
     1062        $this->imidcolor = $aColor ;
    10411063    }
    10421064
    10431065    function SetMidTitle($aTitle) {
    1044         $this->midtitle->Set($aTitle);
     1066        $this->midtitle->Set($aTitle);
    10451067    }
    10461068
    10471069    function SetMidSize($aSize) {
    1048         $this->imidsize = $aSize ;
     1070        $this->imidsize = $aSize ;
    10491071    }
    10501072
    10511073    function SetMidColor($aColor) {
    1052         $this->imidcolor = $aColor ;
     1074        $this->imidcolor = $aColor ;
    10531075    }
    10541076
    10551077    function SetMidCSIM($aTarget,$aAlt='',$aWinTarget='') {
    1056         $this->middlecsimtarget = $aTarget;
    1057         $this->middlecsimwintarget = $aWinTarget;
    1058         $this->middlecsimalt = $aAlt;
    1059     }
    1060 
    1061     function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) { 
     1078        $this->middlecsimtarget = $aTarget;
     1079        $this->middlecsimwintarget = $aWinTarget;
     1080        $this->middlecsimalt = $aAlt;
     1081    }
     1082
     1083    function AddSliceToCSIM($i,$xc,$yc,$radius,$sa,$ea) {
    10621084        //Slice number, ellipse centre (x,y), radius, start angle, end angle
    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         }
     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        }
    11431165    }
    11441166
     
    11461168    function Stroke($img,$aaoption=0) {
    11471169
    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         }
     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        }
    11861208
    11871209    }
    11881210
    11891211    function AddMiddleCSIM($xc,$yc,$r) {
    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";
     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";
    12011223    }
    12021224
    12031225    function StrokeLabel($label,$img,$xc,$yc,$a,$r) {
    12041226
    1205         if( $this->ilabelposadj === 'auto' )
    1206             $this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize;
    1207 
    1208         parent::StrokeLabel($label,$img,$xc,$yc,$a,$r);
     1227        if( $this->ilabelposadj === 'auto' )
     1228        $this->ilabelposadj = (1-$this->imidsize)/2+$this->imidsize;
     1229
     1230        parent::StrokeLabel($label,$img,$xc,$yc,$a,$r);
    12091231
    12101232    }
     
    12151237//===================================================
    12161238// CLASS PieGraph
    1217 // Description: 
     1239// Description:
    12181240//===================================================
    12191241class PieGraph extends Graph {
    1220     private $posx, $posy, $radius;             
    1221     private $legends=array();   
     1242    private $posx, $posy, $radius;
     1243    private $legends=array();
    12221244    public $plots=array();
    12231245    public $pieaa = false ;
    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       
     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
    12351261    function Add($aObj) {
    12361262
    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         }
     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        }
    12571296    }
    12581297
    12591298    function SetAntiAliasing($aFlg=true) {
    1260         $this->pieaa = $aFlg;
    1261     }
    1262        
     1299        $this->pieaa = $aFlg;
     1300    }
     1301
    12631302    function SetColor($c) {
    1264         $this->SetMarginColor($c);
     1303        $this->SetMarginColor($c);
    12651304    }
    12661305
    12671306
    12681307    function DisplayCSIMAreas() {
    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             }
     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        }
    12961336    }
    12971337
    12981338    // Method description
    12991339    function Stroke($aStrokeFileName="") {
    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         }
     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        }
    14451493    }
    14461494} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_pie3d.php

    r267 r284  
    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 956 2007-11-17 13:19:20Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1329 2009-06-20 19:23:30Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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 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        
     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
    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;
    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.');
     61        $this->edgecolor = $aColor;
     62        $this->edgeweight = $aWeight;
    6963    }
    7064
     
    7266    // Must be between 20 and 70 degrees
    7367    function SetAngle($a) {
    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;
     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        }
    7975    }
    8076
    8177    function Add3DSliceToCSIM($i,$xc,$yc,$height,$width,$thick,$sa,$ea) {  //Slice number, ellipse centre (x,y), height, width, start angle, end angle
    8278
    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         }
     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        }
    137133
    138134    }
    139135
    140136    function SetLabels($aLabels,$aLblPosAdj="auto") {
    141         $this->labels = $aLabels;
    142         $this->ilabelposadj=$aLblPosAdj;
    143     }
    144 
    145        
     137        $this->labels = $aLabels;
     138        $this->ilabelposadj=$aLblPosAdj;
     139    }
     140
     141
    146142    // Distance from the pie to the labels
    147143    function SetLabelMargin($m) {
    148         $this->value->SetMargin($m);
    149     }
    150        
     144        $this->value->SetMargin($m);
     145    }
     146
    151147    // Show a thin line from the pie to the label for a specific slice
    152148    function ShowLabelHint($f=true) {
    153         $this->showlabelhint=$f;
    154     }
    155        
     149        $this->showlabelhint=$f;
     150    }
     151
    156152    // Set color of hint line to label for each slice
    157153    function SetLabelHintColor($c) {
    158         $this->labelhintcolor=$c;
     154        $this->labelhintcolor=$c;
    159155    }
    160156
    161157    function SetHeight($aHeight) {
    162       $this->iThickness = $aHeight;
    163     }
    164 
    165 
    166 // Normalize Angle between 0-360
     158        $this->iThickness = $aHeight;
     159    }
     160
     161
     162    // Normalize Angle between 0-360
    167163    function NormAngle($a) {
    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
     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
    186182    function Pie3DSlice($img,$xc,$yc,$w,$h,$sa,$ea,$z,$fillcolor,$shadow=0.65) {
    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();
     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();
    393389    }
    394390
    395391    function SetStartAngle($aStart) {
    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
     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
    403399    function Pie3D($aaoption,$img,$data,$colors,$xc,$yc,$d,$angle,$z,
    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();
     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();
    723716    }
    724717
    725718    function StrokeFullSliceFrame($img,$xc,$yc,$sa,$ea,$w,$h,$z,$edgecolor,$exploderadius,$fulledge) {
    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         }
     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        }
    781776    }
    782777
    783778    function Stroke($img,$aaoption=0) {
    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     
     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
    869872
    870873    // Position the labels of each slice
    871874    function StrokeLabels($label,$img,$a,$xp,$yp,$z) {
    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     }   
     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    }
    920930} // Class
    921931
  • trunk/client/modules/Elezioni/grafici/jpgraph_plotband.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z 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 1106 2009-02-22 20:16:35Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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 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;
     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;
    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 RectPattern($aColor,$aWeight=1) {
    52         $this->color = $aColor;
    53         $this->weight = $aWeight;               
     50
     51    function __construct($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 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);
     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);
    116116    }
    117117}
     
    122122//=====================================================================
    123123class RectPatternHor extends RectPattern {
    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         }
     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        }
    138138    }
    139139}
     
    144144//=====================================================================
    145145class RectPatternVert extends RectPattern {
    146                
    147     function RectPatternVert($aColor="black",$aWeight=1,$aLineSpacing=7) {
    148         parent::RectPattern($aColor,$aWeight);
    149         $this->linespacing = $aLineSpacing;
     146
     147    function __construct($aColor="black",$aWeight=1,$aLineSpacing=7) {
     148        parent::__construct($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 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  
     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
    236236//=====================================================================
    237237// Class RectPatternLDiag
     
    239239//=====================================================================
    240240class RectPatternLDiag extends RectPattern {
    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         }
     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        }
    297297    }
    298298}
     
    308308    // converge.
    309309
    310     function RectPattern3DPlane($aColor="black",$aWeight=1) {
    311         parent::RectPattern($aColor,$aWeight);
    312         $this->SetDensity(10);  // Slightly larger default
     310    function __construct($aColor="black",$aWeight=1) {
     311        parent::__construct($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 RectPatternCross($aColor="black",$aWeight=1) {
    425         parent::RectPattern($aColor,$aWeight);
    426         $this->vert = new RectPatternVert($aColor,$aWeight);
    427         $this->hor  = new RectPatternHor($aColor,$aWeight);
     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);
    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 RectPatternDiagCross($aColor="black",$aWeight=1) {
    461         parent::RectPattern($aColor,$aWeight);
    462         $this->right = new RectPatternRDiag($aColor,$aWeight);
    463         $this->left  = new RectPatternLDiag($aColor,$aWeight);
     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);
    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 RectPatternFactory() {
    495         // Empty
     494    function __construct() {
     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 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        
     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
    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

    r267 r284  
    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 956 2007-11-17 13:19:20Z ljp $
     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 $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. All rights reserved.
    99//========================================================================
    1010
     
    3131    private $imgdata_pushpins = null;
    3232
    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       
     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
    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";
    145         }
    146     }
    147    
     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
    148148    function AddCSIMCircle($x,$y,$r) {
    149         $x = round($x); $y=round($y); $r=round($r);
    150         $this->csimareas="";   
     149        $x = round($x); $y=round($y); $r=round($r);
     150        $this->csimareas="";
    151151        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        
     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     
    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   
    453458    // Create a GD image from the data and return a GD handle
    454459    function GetImg($aMark,$aIdx) {
    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     }
     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   
    470476    function GetAnchor() {
    471         return array($this->anchor_x,$this->anchor_y);
     477        return array($this->anchor_x,$this->anchor_y);
    472478    }
    473479}
     
    476482// Keep a global flag cache to reduce memory usage
    477483$_gFlagCache=array(
    478     1 => null,
    479     2 => null,
    480     3 => null,
    481     4 => null,
     4841 => null,
     4852 => null,
     4863 => null,
     4874 => null,
    482488);
    483489// Only supposed to b called as statics
    484490class FlagCache {
     491   
    485492    static function GetFlagImgByName($aSize,$aName) {
    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);
     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);
    494501    }
    495502}
  • trunk/client/modules/Elezioni/grafici/jpgraph_polar.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1796 2009-09-07 09:37:19Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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 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();
     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();
    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             ++$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!='');
     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!='');
    144145    }
    145146}
     
    159160    private $radius_tick_color='black';
    160161
    161     function PolarAxis($img,$aScale) {
    162         parent::Axis($img,$aScale);
     162    function __construct($img,$aScale) {
     163        parent::__construct($img,$aScale);
    163164    }
    164165
    165166    function ShowAngleDegreeMark($aFlg=true) {
    166         $this->show_angle_mark = $aFlg;
     167        $this->show_angle_mark = $aFlg;
    167168    }
    168169
    169170    function SetAngleStep($aStep) {
    170         $this->angle_step=$aStep;
     171        $this->angle_step=$aStep;
    171172    }
    172173
    173174    function HideTicks($aFlg=true,$aAngleFlg=true) {
    174         parent::HideTicks($aFlg,$aFlg);
    175         $this->show_angle_tick = !$aAngleFlg;
     175        parent::HideTicks($aFlg,$aFlg);
     176        $this->show_angle_tick = !$aAngleFlg;
    176177    }
    177178
    178179    function ShowAngleLabel($aFlg=true) {
    179         $this->show_angle_label = $aFlg;
     180        $this->show_angle_label = $aFlg;
    180181    }
    181182
    182183    function ShowGrid($aMajor=true,$aMinor=false,$aAngle=true) {
    183         $this->show_minor_grid = $aMinor;
    184         $this->show_major_grid = $aMajor;
    185         $this->show_angle_grid = $aAngle ;
     184        $this->show_minor_grid = $aMinor;
     185        $this->show_major_grid = $aMajor;
     186        $this->show_angle_grid = $aAngle ;
    186187    }
    187188
    188189    function SetAngleFont($aFontFam,$aFontStyle=FS_NORMAL,$aFontSize=10) {
    189         $this->angle_fontfam = $aFontFam;
    190         $this->angle_fontstyle = $aFontStyle;
    191         $this->angle_fontsize = $aFontSize;
     190        $this->angle_fontfam = $aFontFam;
     191        $this->angle_fontstyle = $aFontStyle;
     192        $this->angle_fontsize = $aFontSize;
    192193    }
    193194
    194195    function SetColor($aColor,$aRadColor='',$aAngleColor='') {
    195         if( $aAngleColor == '' )
    196             $aAngleColor=$aColor;
    197         parent::SetColor($aColor,$aRadColor);
    198         $this->angle_fontcolor = $aAngleColor;
     196        if( $aAngleColor == '' )
     197        $aAngleColor=$aColor;
     198        parent::SetColor($aColor,$aRadColor);
     199        $this->angle_fontcolor = $aAngleColor;
    199200    }
    200201
    201202    function SetGridColor($aMajorColor,$aMinorColor='',$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;
     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;
    210211    }
    211212
    212213    function SetTickColors($aRadColor,$aAngleColor='') {
    213         $this->radius_tick_color = $aRadColor;
    214         $this->angle_tick_color = $aAngleColor;
    215     }
    216    
     214        $this->radius_tick_color = $aRadColor;
     215        $this->angle_tick_color = $aAngleColor;
     216    }
     217
    217218    // Private methods
    218219    function StrokeGrid($pos) {
    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         }
     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        }
    307308    }
    308309
    309310    function StrokeAngleLabels($pos,$type) {
    310311
    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         }
     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        }
    480495    }
    481496
    482497    function Stroke($pos,$dummy=true) {
    483498
    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
     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
    513530        //
    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);       
     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);
    571590    }
    572591}
     
    574593class PolarScale extends LinearScale {
    575594    private $graph;
    576 
    577     function PolarScale($aMax=0,$graph) {
    578         parent::LinearScale(0,$aMax,'x');
    579         $this->graph = $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;
    580605    }
    581606
    582607    function _Translate($v) {
    583         return parent::Translate($v);
     608        return parent::Translate($v);
    584609    }
    585610
    586611    function PTranslate($aAngle,$aRad) {
    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);
     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);
    604634    }
    605635}
     
    607637class PolarLogScale extends LogScale {
    608638    private $graph;
    609     function PolarLogScale($aMax=1,$graph) {
    610         parent::LogScale(0,$aMax,'x');
    611         $this->graph = $graph;
    612         $this->ticks->SetLabelLogType(LOGLABELS_MAGNITUDE);
    613 
     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;
    614651    }
    615652
    616653    function PTranslate($aAngle,$aRad) {
    617654
    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);
     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);
    636678    }
    637679}
     
    641683    public $axis;
    642684    public $iType=POLAR_360;
    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');
     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');
    649692    }
    650693
    651694    function SetDensity($aDense) {
    652         $this->SetTickDensity(TICKD_NORMAL,$aDense);
     695        $this->SetTickDensity(TICKD_NORMAL,$aDense);
     696    }
     697
     698    function SetClockwise($aFlg) {
     699        $this->scale->SetClockwise($aFlg);
    653700    }
    654701
    655702    function Set90AndMargin($lm=0,$rm=0,$tm=0,$bm=0) {
    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.');
     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');
    662711    }
    663712
    664713    function SetScale($aScale,$rmax=0,$dummy1=1,$dummy2=1,$dummy3=1) {
    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);
     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);
    676726    }
    677727
    678728    function SetType($aType) {
    679         $this->iType = $aType;
     729        $this->iType = $aType;
    680730    }
    681731
    682732    function SetPlotSize($w,$h) {
    683         $this->SetMargin(($this->img->width-$w)/2,($this->img->width-$w)/2,
    684                         ($this->img->height-$h)/2,($this->img->height-$h)/2);
     733        $this->SetMargin(($this->img->width-$w)/2,($this->img->width-$w)/2,
     734                        ($this->img->height-$h)/2,($this->img->height-$h)/2);
    685735    }
    686736
    687737    // Private methods
    688738    function GetPlotsMax() {
    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;
     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;
    697747    }
    698748
    699749    function Stroke($aStrokeFileName="") {
    700750
    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         }
     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        }
    836894    }
    837895}
  • trunk/client/modules/Elezioni/grafici/jpgraph_radar.php

    r267 r284  
    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 1044 2008-07-31 18:34:55Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1783 2009-08-25 11:41:01Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. All rights reserved.
     9 //========================================================================
     10 */
    1111
    1212require_once('jpgraph_plotmark.inc.php');
    1313
     14//===================================================
     15// CLASS RadarLogTicks
     16// Description: Logarithmic ticks
     17//===================================================
    1418class RadarLogTicks extends Ticks {
    15 //---------------
    16 // CONSTRUCTOR
    17     function RadarLogTicks() {
    18     }
    19 //---------------
    20 // PUBLIC METHODS       
    21 
    22     // TODO: Add Argument grid
     19
     20    function __construct() {
     21            // Empty
     22    }
     23
    2324    function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) {
    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     }           
     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    }
    88102}
    89        
    90 class RadarLinearTicks extends Ticks {
     103
     104//===================================================
     105// CLASS RadarLinear
     106// Description: Linear ticks
     107//===================================================
     108class RadarLinearTicks extends Ticks {
    91109
    92110    private $minor_step=1, $major_step=2;
    93111    private $xlabel_offset=0,$xtick_offset=0;
    94112
    95 //---------------
    96 // CONSTRUCTOR
    97     function RadarLinearTicks() {
    98         // Empty
    99     }
    100 
    101 //---------------
    102 // PUBLIC METHODS       
    103 
    104        
     113    function __construct() {
     114        // Empty
     115    }
     116
    105117    // Return major step size in world coordinates
    106118    function GetMajor() {
    107         return $this->major_step;
    108     }
    109        
     119        return $this->major_step;
     120    }
     121
    110122    // Return minor step size in world coordinates
    111123    function GetMinor() {
    112         return $this->minor_step;
    113     }
    114        
     124        return $this->minor_step;
     125    }
     126
    115127    // Set Minor and Major ticks (in world coordinates)
    116128    function Set($aMajStep,$aMinStep=false) {
    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;
     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;
    131141    }
    132142
    133143    function Stroke($aImg,&$grid,$aPos,$aAxisAngle,$aScale,&$aMajPos,&$aMajLabel) {
    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         }
     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        }
    189211    }
    190212}
    191213
    192        
    193214
    194215//===================================================
     
    198219class RadarAxis extends AxisPrototype {
    199220    public $title=null;
    200     private $title_color="navy";
     221    private $title_color='navy';
    201222    private $len=0;
    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
     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
    221234    // $aAxisAngle = Axis angle
    222     // $grid                    = Returns an array with positions used to draw the grid
    223     //  $lf                     = Label flag, TRUE if the axis should have labels
     235    // $grid   = Returns an array with positions used to draw the grid
     236    // $lf   = Label flag, TRUE if the axis should have labels
    224237    function Stroke($pos,$aAxisAngle,&$grid,$title,$lf) {
    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        
     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
    268284    function _StrokeAxisTitle($pos,$aAxisAngle,$title) {
    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        
     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
    310329} // Class
    311330
     
    320339    private $show=false, $weight=1;
    321340
    322 //------------
    323 // CONSTRUCTOR
    324     function RadarGrid() {
    325     }
    326 
    327 // PUBLIC METHODS
     341    function __construct() {
     342        // Empty
     343    }
     344
    328345    function SetColor($aMajColor) {
    329         $this->grid_color = $aMajColor;
    330     }
    331        
     346        $this->grid_color = $aMajColor;
     347    }
     348
    332349    function SetWeight($aWeight) {
    333         $this->weight=$aWeight;
    334     }
    335        
     350        $this->weight=$aWeight;
     351    }
     352
    336353    // Specify if grid should be dashed, dotted or solid
    337354    function SetLineStyle($aType) {
    338         $this->type = $aType;
    339     }
    340        
     355        $this->type = $aType;
     356    }
     357
    341358    // Decide if both major and minor grid should be displayed
    342359    function Show($aShowMajor=true) {
    343         $this->show=$aShowMajor;
    344     }
    345    
    346 //----------------
    347 // PRIVATE METHODS     
     360        $this->show=$aShowMajor;
     361    }
     362
    348363    function Stroke($img,$grid) {
    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         }
     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        }
    372391    }
    373392} // Class
     
    380399class RadarPlot {
    381400    public $mark=null;
    382     public $legend="";
     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
    383407    private $data=array();
    384408    private $fill=false, $fill_color=array(200,170,180);
     
    386410    private $weight=1;
    387411    private $linestyle='solid';
    388 //---------------
    389 // CONSTRUCTOR
    390     function RadarPlot($data) {
    391         $this->data = $data;
    392         $this->mark = new PlotMark();
    393     }
    394 
    395 //---------------
    396 // PUBLIC METHODS       
     412
     413    //---------------
     414    // CONSTRUCTOR
     415    function __construct($data) {
     416        $this->data = $data;
     417        $this->mark = new PlotMark();
     418    }
     419
    397420    function Min() {
    398         return Min($this->data);
    399     }
    400        
     421        return Min($this->data);
     422    }
     423
    401424    function Max() {
    402         return Max($this->data);
    403     }
    404        
     425        return Max($this->data);
     426    }
     427
    405428    function SetLegend($legend) {
    406         $this->legend=$legend;
     429        $this->legend=$legend;
    407430    }
    408431
    409432    function SetLineStyle($aStyle) {
    410         $this->linestyle=$aStyle;
    411     }
    412        
     433        $this->linestyle=$aStyle;
     434    }
     435
    413436    function SetLineWeight($w) {
    414         $this->weight=$w;
    415     }
    416                
     437        $this->weight=$w;
     438    }
     439
    417440    function SetFillColor($aColor) {
    418         $this->fill_color = $aColor;
    419         $this->fill = true;             
    420     }
    421    
     441        $this->fill_color = $aColor;
     442        $this->fill = true;
     443    }
     444
    422445    function SetFill($f=true) {
    423         $this->fill = $f;
    424     }
    425    
     446        $this->fill = $f;
     447    }
     448
    426449    function SetColor($aColor,$aFillColor=false) {
    427         $this->color = $aColor;
    428         if( $aFillColor ) {
    429             $this->SetFillColor($aFillColor);
    430             $this->fill = true;
    431         }
    432     }
    433        
     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
    434464    function GetCSIMareas() {
    435         JpGraphError::RaiseL(18001);
    436 //("Client side image maps not supported for RadarPlots.");
    437     }
    438        
     465        return $this->csimareas;
     466    }
     467
    439468    function Stroke($img, $pos, $scale, $startangle) {
    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
     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
    489533    function GetCount() {
    490         return count($this->data);
    491     }
    492        
     534        return count($this->data);
     535    }
     536
    493537    function Legend($graph) {
    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        
     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
    501548} // Class
    502549
     
    508555    public $grid,$axis=null;
    509556    private $posx,$posy;
    510     private $len;               
     557    private $len;
    511558    private $axis_title=null;
    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);
     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);
    533569    }
    534570
    535571    function HideTickMarks($aFlag=true) {
    536                 $this->axis->scale->ticks->SupressTickMarks($aFlag);
    537     }
    538    
     572        $this->axis->scale->ticks->SupressTickMarks($aFlag);
     573    }
     574
    539575    function ShowMinorTickmarks($aFlag=true) {
    540         $this->yscale->ticks->SupressMinorTickMarks(!$aFlag);
    541     }
    542        
     576        $this->yscale->ticks->SupressMinorTickMarks(!$aFlag);
     577    }
     578
    543579    function SetScale($axtype,$ymin=1,$ymax=1,$dummy1=null,$dumy2=null) {
    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();         
     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();
    560596    }
    561597
    562598    function SetSize($aSize) {
    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;
     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;
    567604    }
    568605
    569606    function SetPlotSize($aSize) {
    570         $this->SetSize($aSize);
     607        $this->SetSize($aSize);
    571608    }
    572609
    573610    function SetTickDensity($densy=TICKD_NORMAL,$dummy1=null) {
    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         }
     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        }
    592629    }
    593630
    594631    function SetPos($px,$py=0.5) {
    595         $this->SetCenter($px,$py);
     632        $this->SetCenter($px,$py);
    596633    }
    597634
    598635    function SetCenter($px,$py=0.5) {
    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        
     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
    616676    function GetPlotsYMinMax($aPlots) {
    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     }   
     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    }
    628707
    629708    // Stroke the Radar graph
    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         }
     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                }
    735857    }
    736858} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_regstat.php

    r267 r284  
    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 781 2006-10-08 08:07:47Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1131 2009-03-11 20:08:24Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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 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         }
     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        }
    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://astronomy.swin.edu.au/~pbourke/curves/bezier/
    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://local.wasp.uwa.edu.au/~pbourke/geometry/bezier/index2.html
     119     */
    120120    private $datax = array();
    121121    private $datay = array();
    122122    private $n=0;
    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 
     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     */
    146151    function Get($steps) {
    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  
     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     */
    161174    function GetPoint($mu) {
    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);
     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);
    198211    }
    199212}
  • trunk/client/modules/Elezioni/grafici/jpgraph_rgb.inc.php

    r267 r284  
    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 1049 2008-08-01 19:58:07Z 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 1893 2009-10-02 23:15:25Z ljp $
    88//
    9 // Copyright (c) Aditus Consulting. All rights reserved.
     9// Copyright (c) Asial Corporation. All rights reserved.
    1010//========================================================================
    1111
    1212
    13 //===================================================
     13/*===================================================
    1414// CLASS RGB
    1515// Description: Color definitions as RGB triples
    1616//===================================================
     17*/
     18
    1719class RGB {
    18     public $rgb_table; 
     20    public $rgb_table;
    1921    public $img;
    2022
    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));         
     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));
    462469    }
    463 //----------------
    464 // PUBLIC METHODS
     470
     471
     472    //----------------
     473    // PUBLIC METHODS
    465474    // Colors can be specified as either
    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 
     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
    470479    // RGB triple.
     480
    471481    function Color($aColor) {
    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));
     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        }
    542540    }
    543        
     541
    544542    // Compare two colors
    545543    // return true if equal
    546544    function Equal($aCol1,$aCol2) {
    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;
     545        $c1 = $this->Color($aCol1);
     546        $c2 = $this->Color($aCol2);
     547        return $c1[0]==$c2[0] && $c1[1]==$c2[1] && $c1[2]==$c2[2] ;
    553548    }
    554        
     549
    555550    // Allocate a new color in the current image
    556551    // Return new color index, -1 if no more colors could be allocated
    557552    function Allocate($aColor,$aAlpha=0.0) {
    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));
     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));
    567563    }
     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
    568613} // Class
    569614
  • trunk/client/modules/Elezioni/grafici/jpgraph_scatter.php

    r267 r284  
    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 957 2007-12-01 14:00:29Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1397 2009-06-27 21:34:14Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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     function FieldArrow() {
     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
    2426    }
    2527
    2628    function SetSize($aSize,$aArrowSize=2) {
    27         $this->iSize = $aSize;
    28         $this->iArrowSize = $aArrowSize;
     29        $this->iSize = $aSize;
     30        $this->iArrowSize = $aArrowSize;
    2931    }
    3032
    3133    function SetColor($aColor) {
    32         $this->iColor = $aColor;
     34        $this->iColor = $aColor;
    3335    }
    3436
    3537    function Stroke($aImg,$x,$y,$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);
     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);
    5658    }
    5759}
     
    6567    private $iAngles = array();
    6668    private $iCallback = '';
    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();
     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();
    8183    }
    8284
    8385    function SetCallback($aFunc) {
    84         $this->iCallback = $aFunc;
     86        $this->iCallback = $aFunc;
    8587    }
    8688
    8789    function Stroke($img,$xscale,$yscale) {
    8890
    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        
     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
    118120    // Framework function
    119121    function Legend($aGraph) {
    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     }   
     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    }
    125127}
    126128
     
    130132//===================================================
    131133class ScatterPlot extends Plot {
    132     public $mark = '';
     134    public $mark,$link;
    133135    private $impuls = false;
    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       
     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
    150154    function SetImpuls($f=true) {
    151         $this->impuls = $f;
    152     }   
     155        $this->impuls = $f;
     156    }
     157
     158    function SetStem($f=true) {
     159        $this->impuls = $f;
     160    }
    153161
    154162    // Combine the scatter plot points with a line
    155     function SetLinkPoints($aFlag=true,$aColor="black",$aWeight=1) {
    156         $this->linkpoints=$aFlag;
    157         $this->linkpointcolor=$aColor;
    158         $this->linkpointweight=$aWeight;
     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;
    159168    }
    160169
    161170    function Stroke($img,$xscale,$yscale) {
    162171
    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        
     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
    222233    // Framework function
    223234    function Legend($aGraph) {
    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     }   
     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    }
    229240} // Class
    230241/* EOF */
  • trunk/client/modules/Elezioni/grafici/jpgraph_stock.php

    r267 r284  
    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 957 2007-12-01 14:00:29Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1364 2009-06-24 07:07:44Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. All rights reserved.
     9 //========================================================================
     10 */
    1111
    1212//===================================================
     
    1818    private $iEndLines=1;
    1919    private $iStockColor1='white',$iStockColor2='darkred',$iStockColor3='darkred';
    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;
     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;
    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             else
    70                 $exist_x = true;
    71         }
    72         else
    73             $exist_x = false;
     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        }
    7477
    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) {
     78        if( $exist_x ) {
     79            $xs=$this->coords[1][0];
     80        }
     81        else {
     82            $xs=0;
     83        }
    8384
    84             //If value is NULL, then don't draw a bar at all
    85             if ($this->coords[0][$i] === null) continue;
     85        $ts = $this->iTupleSize;
     86        $this->csimareas = '';
     87        for( $i=0; $i<$n; ++$i) {
    8688
    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]);
     89            //If value is NULL, then don't draw a bar at all
     90            if ($this->coords[0][$i*$ts] === null) continue;
    9691
    97             $dx = floor($this->iWidth/2);
    98             $xl = $xt - $dx;
    99             $xr = $xt + $dx;
     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);
    100100
    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);
     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]);
    113106
    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);
     107            $dx = floor($this->iWidth/2);
     108            $xl = $xt - $dx;
     109            $xr = $xt + $dx;
    125110
    126             if( $this->iEndLines ) {
    127                 $img->Line($xl,$ymax,$xr,$ymax);
    128                 $img->Line($xl,$ymin,$xr,$ymin);
    129             }
     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            }
    130125
    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);
     126            $img->Rectangle($xl,$yopen,$xr,$yclose);
    134127
    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;
     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;
    149163    }
    150164
     
    159173class BoxPlot extends StockPlot {
    160174    private $iPColor='black',$iNColor='white';
    161     function BoxPlot($datay,$datax=false) {
    162         $this->iTupleSize=5;
    163         parent::StockPlot($datay,$datax);
     175
     176    function __construct($datay,$datax=false) {
     177        $this->iTupleSize=5;
     178        parent::__construct($datay,$datax);
    164179    }
    165180
    166181    function SetMedianColor($aPos,$aNeg) {
    167         $this->iPColor = $aPos;
    168         $this->iNColor = $aNeg;
     182        $this->iPColor = $aPos;
     183        $this->iNColor = $aNeg;
    169184    }
    170185
    171186    function ModBox($img,$xscale,$yscale,$i,$xl,$xr,$neg) {
    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);
     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);
    179194    }
    180195}
  • trunk/client/modules/Elezioni/grafici/jpgraph_text.inc.php

    r267 r284  
    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 1048 2008-08-01 19:56:46Z 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 1844 2009-09-26 17:05:31Z ljp $
    88//
    9 // Copyright (c) Aditus Consulting. All rights reserved.
     9// Copyright (c) Asial Corporation. All rights reserved.
    1010//========================================================================
    1111
     
    1616//===================================================
    1717class Text {
    18     public $t,$margin=0;
     18    public $t;
    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_FONT1,$font_style=FS_NORMAL,$font_size=12;
    24     protected $boxed=false;     // Should the text be boxed
     23    public $font_family=FF_DEFAULT,$font_style=FS_NORMAL; // old. FF_FONT1
     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 
    30 //---------------
    31 // CONSTRUCTOR
     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
    3237
    3338    // Create new text at absolute pixel coordinates
    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       
     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
    4550    // Set the string in the text object
    4651    function Set($aTxt) {
    47         $this->t = $aTxt;
    48     }
    49        
     52        $this->t = $aTxt;
     53    }
     54
    5055    // Alias for Pos()
    5156    function SetPos($aXAbsPos=0,$aYAbsPos=0,$aHAlign="left",$aVAlign="top") {
    52         //$this->Pos($aXAbsPos,$aYAbsPos,$aHAlign,$aVAlign);
    53         $this->x = $aXAbsPos;
    54         $this->y = $aYAbsPos;
    55         $this->halign = $aHAlign;
    56         $this->valign = $aVAlign;
     57    //$this->Pos($aXAbsPos,$aYAbsPos,$aHAlign,$aVAlign);
     58        $this->x = $aXAbsPos;
     59        $this->y = $aYAbsPos;
     60        $this->halign = $aHAlign;
     61        $this->valign = $aVAlign;
    5762    }
    5863
    5964    function SetScalePos($aX,$aY) {
    60         $this->iScalePosX = $aX;
    61         $this->iScalePosY = $aY;
    62     }
    63        
     65        $this->iScalePosX = $aX;
     66        $this->iScalePosY = $aY;
     67    }
     68
    6469    // Specify alignment for the text
    6570    function Align($aHAlign,$aVAlign="top",$aParagraphAlign="") {
    66         $this->halign = $aHAlign;
    67         $this->valign = $aVAlign;
    68         if( $aParagraphAlign != "" )
    69             $this->paragraph_align = $aParagraphAlign;
    70     }           
    71    
     71        $this->halign = $aHAlign;
     72        $this->valign = $aVAlign;
     73        if( $aParagraphAlign != "" )
     74            $this->paragraph_align = $aParagraphAlign;
     75    }
     76
    7277    // Alias
    7378    function SetAlign($aHAlign,$aVAlign="top",$aParagraphAlign="") {
    74         $this->Align($aHAlign,$aVAlign,$aParagraphAlign);
     79        $this->Align($aHAlign,$aVAlign,$aParagraphAlign);
    7580    }
    7681
    7782    // Specifies the alignment for a multi line text
    7883    function ParagraphAlign($aAlign) {
    79         $this->paragraph_align = $aAlign;
     84        $this->paragraph_align = $aAlign;
    8085    }
    8186
    8287    // Specifies the alignment for a multi line text
    8388    function SetParagraphAlign($aAlign) {
    84         $this->paragraph_align = $aAlign;
     89        $this->paragraph_align = $aAlign;
    8590    }
    8691
    8792    function SetShadow($aShadowColor='gray',$aShadowWidth=3) {
    88         $this->ishadowwidth=$aShadowWidth;
    89         $this->shadow=$aShadowColor;
    90         $this->boxed=true;
     93        $this->ishadowwidth=$aShadowWidth;
     94        $this->shadow=$aShadowColor;
     95        $this->boxed=true;
    9196    }
    9297
    9398    function SetWordWrap($aCol) {
    94         $this->iWordwrap = $aCol ;
    95     }
    96        
     99        $this->iWordwrap = $aCol ;
     100    }
     101
    97102    // Specify that the text should be boxed. fcolor=frame color, bcolor=border color,
    98103    // $shadow=drop shadow should be added around the text.
    99104    function SetBox($aFrameColor=array(255,255,255),$aBorderColor=array(0,0,0),$aShadowColor=false,$aCornerRadius=4,$aShadowWidth=3) {
    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        
     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
    114127    // Hide the text
    115128    function Hide($aHide=true) {
    116         $this->hide=$aHide;
    117     }
    118        
    119     // This looks ugly since it's not a very orthogonal design 
     129        $this->hide=$aHide;
     130    }
     131
     132    // This looks ugly since it's not a very orthogonal design
    120133    // but I added this "inverse" of Hide() to harmonize
    121     // with some classes which I designed more recently (especially) 
     134    // with some classes which I designed more recently (especially)
    122135    // jpgraph_gantt
    123136    function Show($aShow=true) {
    124         $this->hide=!$aShow;
    125     }
    126        
     137        $this->hide=!$aShow;
     138    }
     139
    127140    // Specify font
    128141    function SetFont($aFamily,$aStyle=FS_NORMAL,$aSize=10) {
    129         $this->font_family=$aFamily;
    130         $this->font_style=$aStyle;
    131         $this->font_size=$aSize;
    132     }
    133                        
     142        $this->font_family=$aFamily;
     143        $this->font_style=$aStyle;
     144        $this->font_size=$aSize;
     145    }
     146
    134147    // Center the text between $left and $right coordinates
    135148    function Center($aLeft,$aRight,$aYAbsPos=false) {
    136         $this->x = $aLeft + ($aRight-$aLeft     )/2;
    137         $this->halign = "center";
    138         if( is_numeric($aYAbsPos) )
    139             $this->y = $aYAbsPos;               
    140     }
    141        
     149        $this->x = $aLeft + ($aRight-$aLeft )/2;
     150        $this->halign = "center";
     151        if( is_numeric($aYAbsPos) )
     152            $this->y = $aYAbsPos;
     153    }
     154
    142155    // Set text color
    143156    function SetColor($aColor) {
    144         $this->color = $aColor;
    145     }
    146        
     157        $this->color = $aColor;
     158    }
     159
    147160    function SetAngle($aAngle) {
    148         $this->SetOrientation($aAngle);
    149     }
    150        
     161        $this->SetOrientation($aAngle);
     162    }
     163
    151164    // Orientation of text. Note only TTF fonts can have an arbitrary angle
    152165    function SetOrientation($aDirection=0) {
    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        
     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
    162176    // Total width of text
    163177    function GetWidth($aImg) {
    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        
     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
    169183    // Hight of font
    170184    function GetFontHeight($aImg) {
    171         $aImg->SetFont($this->font_family,$this->font_style,$this->font_size);
    172         $h = $aImg->GetFontHeight();
    173         return $h;
     185        $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size);
     186        $h = $aImg->GetFontHeight();
     187        return $h;
    174188
    175189    }
    176190
    177191    function GetTextHeight($aImg) {
    178         $aImg->SetFont($this->font_family,$this->font_style,$this->font_size); 
    179         $h = $aImg->GetTextHeight($this->t,$this->dir);
    180         return $h;
     192        $aImg->SetFont($this->font_family,$this->font_style,$this->raw_font_size);
     193        $h = $aImg->GetTextHeight($this->t,$this->dir);
     194        return $h;
    181195    }
    182196
    183197    function GetHeight($aImg) {
    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;
     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;
    188202    }
    189203
     
    191205    // on the context.
    192206    function SetMargin($aMarg) {
    193         $this->margin = $aMarg;
     207        $this->margin = $aMarg;
    194208    }
    195209
    196210    function StrokeWithScale($aImg,$axscale,$ayscale) {
    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         }
     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        }
    206219    }
    207220
    208221    function SetCSIMTarget($aURITarget,$aAlt='',$aWinTarget='') {
    209         $this->iCSIMtarget = $aURITarget;
    210         $this->iCSIMalt = $aAlt;
    211         $this->iCSIMWinTarget = $aWinTarget;
     222        $this->iCSIMtarget = $aURITarget;
     223        $this->iCSIMalt = $aAlt;
     224        $this->iCSIMWinTarget = $aWinTarget;
    212225    }
    213226
    214227    function GetCSIMareas() {
    215         if( $this->iCSIMtarget !== '' )
    216             return $this->iCSIMarea;
    217         else
    218             return '';
     228        if( $this->iCSIMtarget !== '' ) {
     229            return $this->iCSIMarea;
     230        }
     231        else {
     232            return '';
     233        }
    219234    }
    220235
     
    222237    function Stroke($aImg,$x=null,$y=null) {
    223238
    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 
     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;
    267323    }
    268324} // Class
  • trunk/client/modules/Elezioni/grafici/jpgraph_ttf.inc.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z 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 1858 2009-09-28 14:39:51Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. All rights reserved.
    99//========================================================================
    1010
     
    2727define("FF_SIMSUN",30);
    2828define("FF_CHINESE",31);
    29 define("FF_BIG5",31);
     29define("FF_BIG5",32);
    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 
    54 define("FF_SPEEDO",71);         // This font is also known as Bauer (Used for gauge fascia)
    55 define("FF_DIGITAL",72);        // Digital readout font
    56 define("FF_COMPUTER",73);       // The classic computer font
    57 define("FF_CALCULATOR",74);     // Triad font
     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)
     57define("FF_DIGITAL",72); // Digital readout font
     58define("FF_COMPUTER",73); // The classic computer font
     59define("FF_CALCULATOR",74); // Triad font
    5860
    5961define("FF_USERFONT",90);
     
    7880define("FF_FONT2",4);
    7981
     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
     89define('CHINESE_TTF_FONT','bkai00mp.ttf');
     90
     91// Special unicode greek language support
     92define("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
     96define("GREEK_FROM_WINDOWS",false);
     97
     98// Special unicode cyrillic language support
     99define("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
     104define("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//
     131define('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/
     136define('MINCHO_TTF_FONT','ipam.ttf');
     137define('PMINCHO_TTF_FONT','ipamp.ttf');
     138define('GOTHIC_TTF_FONT','ipag.ttf');
     139define('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.
     144define('ASSUME_EUCJP_ENCODING',false);
     145
     146
     147// Default font family
     148define('FF_DEFAULT', FF_DV_SANSSERIF);
     149
     150
     151
    80152//=================================================================
    81153// CLASS LanguageConv
    82 // Description: 
     154// Description:
    83155// Converts various character encoding into proper
    84156// UTF-8 depending on how the library have been configured and
     
    89161
    90162    function Convert($aTxt,$aFF) {
    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;
     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;
    138210    }
    139211
    140212    // Translate iso encoding to unicode
    141213    public static function iso2uni ($isoline){
    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;
     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;
    149221    }
    150222
    151223    // Translate greek iso encoding to unicode
    152224    public static function gr_iso2uni ($isoline) {
    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;
     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;
    160232    }
    161233
    162234    // Translate greek win encoding to unicode
    163235    public static function gr_win2uni ($winline) {
    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;
     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;
    176248    }
    177249
    178250    public static function heb_iso2uni($isoline) {
    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);
     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);
    188260    }
    189261}
     
    191263//=============================================================
    192264// CLASS TTF
    193 // Description: Handle TTF font names and mapping and loading of 
     265// Description: Handle TTF font names and mapping and loading of
    194266//              font files
    195267//=============================================================
     
    197269    private $font_files,$style_names;
    198270
    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 =>'' ) ,
     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 =>'' ) ,
    251322
    252323            /* Chinese fonts */
    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 =>'' ),
     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 =>'' ),
    261339
    262340            /* Japanese fonts */
    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 =>'' ),   
     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 =>'' ),
    283364
    284365            /* Hebrew fonts */
    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 =>'' ),   
     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 =>'' ),
    299383
    300384            /* Misc fonts */
    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 =>'' ), 
     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 =>'' ),
    317410
    318411            /* Dejavu fonts */
    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       
     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
    366467    // Create the TTF file from the font specification
    367468    function File($family,$style=FS_NORMAL) {
    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;
     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;
    390515    }
    391516
    392517    function SetUserFont($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    393         $this->font_files[FF_USERFONT] =
    394             array(FS_NORMAL     => $aNormal, 
    395                   FS_BOLD       => $aBold,   
    396                   FS_ITALIC     => $aItalic,   
    397                   FS_BOLDITALIC => $aBoldIt ) ;
     518        $this->font_files[FF_USERFONT] =
     519                array(FS_NORMAL     => $aNormal,
     520                          FS_BOLD => $aBold,
     521                          FS_ITALIC => $aItalic,
     522                          FS_BOLDITALIC => $aBoldIt ) ;
    398523    }
    399524
    400525    function SetUserFont1($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    401         $this->font_files[FF_USERFONT1] =
    402             array(FS_NORMAL     => $aNormal, 
    403                   FS_BOLD       => $aBold,   
    404                   FS_ITALIC     => $aItalic,   
    405                   FS_BOLDITALIC => $aBoldIt ) ;
     526        $this->font_files[FF_USERFONT1] =
     527                array(FS_NORMAL     => $aNormal,
     528                          FS_BOLD => $aBold,
     529                          FS_ITALIC => $aItalic,
     530                          FS_BOLDITALIC => $aBoldIt ) ;
    406531    }
    407532
    408533    function SetUserFont2($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    409         $this->font_files[FF_USERFONT2] =
    410             array(FS_NORMAL     => $aNormal, 
    411                   FS_BOLD       => $aBold,   
    412                   FS_ITALIC     => $aItalic,   
    413                   FS_BOLDITALIC => $aBoldIt ) ;
     534        $this->font_files[FF_USERFONT2] =
     535                array(FS_NORMAL     => $aNormal,
     536                          FS_BOLD => $aBold,
     537                          FS_ITALIC => $aItalic,
     538                          FS_BOLDITALIC => $aBoldIt ) ;
    414539    }
    415540
    416541    function SetUserFont3($aNormal,$aBold='',$aItalic='',$aBoldIt='') {
    417         $this->font_files[FF_USERFONT3] =
    418             array(FS_NORMAL     => $aNormal, 
    419                   FS_BOLD       => $aBold,   
    420                   FS_ITALIC     => $aItalic,   
    421                   FS_BOLDITALIC => $aBoldIt ) ;
     542        $this->font_files[FF_USERFONT3] =
     543                array(FS_NORMAL     => $aNormal,
     544                          FS_BOLD => $aBold,
     545                          FS_ITALIC => $aItalic,
     546                          FS_BOLDITALIC => $aBoldIt ) ;
    422547    }
    423548
     
    425550
    426551
     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//=============================================================================
     558class  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
    427630
    428631?>
  • trunk/client/modules/Elezioni/grafici/jpgraph_utils.inc.php

    r267 r284  
    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 1091 2009-01-18 22:57:40Z ljp $
    7 //
    8 // Copyright (c) Aditus Consulting. 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 1777 2009-08-23 17:34:36Z ljp $
     7 //
     8 // Copyright (c) Asial Corporation. 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 FuncGenerator($aFunc,$aXFunc='') {
    21         $this->iFunc = $aFunc;
    22         $this->iXFunc = $aXFunc;
    23     }
    24        
     19
     20    function __construct($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);
    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 //=============================================================================
    54 class  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 '';
     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);
    12045    }
    12146}
     
    15176
    15277    static function UseWeekFormat($aFlg) {
    153         self::$iUseWeeks = $aFlg;
     78        self::$iUseWeeks = $aFlg;
    15479    }
    15580
    15681    static function doYearly($aType,$aMinor=false) {
    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         }
     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        }
    209134    }
    210135
    211136    static function doDaily($aType,$aMinor=false) {
    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         }
     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        }
    256181    }
    257182
    258183    static function doWeekly($aType,$aMinor=false) {
    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         }
     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        }
    302227    }
    303228
    304229    static function doMonthly($aType,$aMinor=false) {
    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);
     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);
    393318    }
    394319
    395320    static function GetTicks($aData,$aType=1,$aMinor=false,$aEndPoints=false) {
    396         $n = count($aData);
    397         return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints);
     321        $n = count($aData);
     322        return self::GetTicksFromMinMax($aData[0],$aData[$n-1],$aType,$aMinor,$aEndPoints);
    398323    }
    399324
    400325    static function GetAutoTicks($aMin,$aMax,$aMaxTicks=10,$aMinor=false) {
    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         }
     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        }
    441362    }
    442363
    443364    static function GetTicksFromMinMax($aMin,$aMax,$aType,$aMinor=false,$aEndPoints=false) {
    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 
     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    }
    482402}
    483403
     
    486406//=============================================================================
    487407Class ReadFileData {
    488 
    489408    //----------------------------------------------------------------------------
    490409    // Desciption:
    491     // Read numeric data from a file. 
    492     // Each value should be separated by either a new line or by a specified 
     410    // Read numeric data from a file.
     411    // Each value should be separated by either a new line or by a specified
    493412    // separator character (default is ',').
    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 
     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
    496415    // file will be discarded.
    497416    //
    498     // Returns: 
     417    // Returns:
    499418    // The number of data values read on success, FALSE on failure
    500419    //----------------------------------------------------------------------------
    501420    static function FromCSV($aFile,&$aData,$aSepChar=',',$aMaxLineLength=1024) {
    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     }
     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
    525594}
    526595
     596define('__LR_EPSILON', 1.0e-8);
     597//=============================================================================
     598// Class LinearRegression
     599//=============================================================================
     600class 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
    527685?>
  • trunk/client/modules/Elezioni/grafici/lang/de.inc.php

    r267 r284  
    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 // Ver:         $Id: de.inc.php 1017 2008-07-08 06:09:28Z ljp $
     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 $
    89//
    910// Copyright (c)
     
    1819*/
    192010  => array('<table border="1"><tr><td style="color:darkred;font-size:1.2em;"><b>JpGraph Fehler:</b>
    20 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),
     21HTTP 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),
    2122
    2223/*
    2324** Setup Fehler
    2425*/
    25 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),
    26 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),
     2611 => array('Es wurde kein Pfad fÃŒr CACHE_DIR angegeben. Bitte gib einen Pfad CACHE_DIR in der Datei jpg-config.inc an.',0),
     2712 => 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),
    272813 => array('The installed PHP version (%s) is not compatible with this release of the library. The library requires at least PHP version %s',2),
    2829
     
    34352002 => array('Unbekannte Vorlage im Aufruf von BarPlot::SetPattern().',0),
    35362003 => array('Anzahl der X- und Y-Koordinaten sind nicht identisch. Anzahl der X-Koordinaten: %d; Anzahl der Y-Koordinaten: %d.',2),
    36 2004 => array('Alle Werte für ein Balkendiagramm (barplot) müssen numerisch sein. Du hast den Wert nr [%d] == %s angegeben.',2),
    37 2005 => array('Du hast einen leeren Vektor für die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0),
    38 2006 => array('Unbekannte Position für die Werte der Balken: %s.',1),
     372004 => array('Alle Werte fÃŒr ein Balkendiagramm (barplot) mÃŒssen numerisch sein. Du hast den Wert nr [%d] == %s angegeben.',2),
     382005 => array('Du hast einen leeren Vektor fÃŒr die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0),
     392006 => array('Unbekannte Position fÃŒr die Werte der Balken: %s.',1),
    39402007 => array('Kann GroupBarPlot nicht aus einem leeren Vektor erzeugen.',0),
    40412008 => array('GroupBarPlot Element nbr %d wurde nicht definiert oder ist leer.',0),
     
    43442011 => array('AccBarPlot-Element nbr %d wurde nicht definiert oder ist leer.',1),
    44452012 => 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),
    45 2013 => array('Du hast einen leeren Vektor für die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0),
     462013 => array('Du hast einen leeren Vektor fÃŒr die Schattierungsfarben im Balkendiagramm (barplot) angegeben.',0),
    46472014 => array('Die Anzahl der Datenpunkte jeder Datenreihe in AccBarPlot muss gleich sein.',0),
    47482015 => array('Individual bar plots in an AccBarPlot or GroupBarPlot can not have specified X-coordinates',0),
     
    5253*/
    5354
    54 3001 => array('Es ist nur möglich, entweder SetDateAlign() oder SetTimeAlign() zu benutzen, nicht beides!',0),
     553001 => array('Es ist nur möglich, entweder SetDateAlign() oder SetTimeAlign() zu benutzen, nicht beides!',0),
    5556
    5657/*
     
    6465*/
    6566
    66 5001 => array('Unbekannte Flaggen-Größe (%d).',1),
     675001 => array('Unbekannte Flaggen-Größe (%d).',1),
    67685002 => array('Der Flaggen-Index %s existiert nicht.',1),
    68 5003 => array('Es wurde eine ungültige Ordnungszahl (%d) für den Flaggen-Index angegeben.',1),
     695003 => array('Es wurde eine ungÃŒltige Ordnungszahl (%d) fÃŒr den Flaggen-Index angegeben.',1),
    69705004 => 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),
    7071
     
    7475*/
    7576
    76 6001 => array('Interner Fehler. Die Höhe für ActivityTitles ist < 0.',0),
    77 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),
    78 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),
    79 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),
     776001 => array('Interner Fehler. Die Höhe fÃŒr ActivityTitles ist < 0.',0),
     786002 => 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),
     796003 => 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),
     806004 => 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),
    80816005 => array('SetScale() ist nicht sinnvoll bei Gantt-Diagrammen.',0),
    81 6006 => array('Das Gantt-Diagramm kann nicht automatisch skaliert werden. Es existieren keine Aktivitäten mit Termin. [GetBarMinMax() start >= n]',0),
    82 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),
    83 6008 => array('Du hast eine Bedingung angegeben von Reihe=%d bis Reihe=%d, die keine Aktivität hat.',2),
     826006 => array('Das Gantt-Diagramm kann nicht automatisch skaliert werden. Es existieren keine AktivitÀten mit Termin. [GetBarMinMax() start >= n]',0),
     836007 => 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),
     846008 => array('Du hast eine Bedingung angegeben von Reihe=%d bis Reihe=%d, die keine AktivitÀt hat.',2),
    84856009 => array('Unbekannter Bedingungstyp von Reihe=%d bis Reihe=%d',2),
    85 6010 => array('Ungültiger Icon-Index für das eingebaute Gantt-Icon [%d]',1),
    86 6011 => array('Argument für IconImage muss entweder ein String oder ein Integer sein.',0),
     866010 => array('UngÃŒltiger Icon-Index fÃŒr das eingebaute Gantt-Icon [%d]',1),
     876011 => array('Argument fÃŒr IconImage muss entweder ein String oder ein Integer sein.',0),
    87886012 => array('Unbekannter Typ bei der Gantt-Objekt-Title-Definition.',0),
    88 6015 => array('Ungültige vertikale Position %d',1),
    89 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),
     896015 => array('UngÃŒltige vertikale Position %d',1),
     906016 => 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),
    90916017 => array('Unbekannter Datumstyp in GanttScale (%s).',1),
    91 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),
    92 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),
    93 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),
    94 6021 => array('Unbekanntes Format für die Woche.',0),
     926018 => 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),
     936019 => 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),
     946020 => 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),
     956021 => array('Unbekanntes Format fÃŒr die Woche.',0),
    95966022 => array('Die Gantt-Skala wurde nicht eingegeben.',0),
    96976023 => 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),
     
    98996025 => array('Der CSIM-Alt-Text muss als String angegeben werden. Der Beginn des Alt-Textes ist: %d',1),
    991006027 => array('Der Fortschrittswert muss im Bereich [0, 1] liegen.',0),
    100 6028 => array('Die eingegebene Höhe (%d) für GanttBar ist nicht im zulässigen Bereich.',1),
    101 6029 => array('Der Offset für die vertikale Linie muss im Bereich [0,1] sein.',0),
    102 6030 => array('Unbekannte Pfeilrichtung für eine Verbindung.',0),
    103 6031 => array('Unbekannter Pfeiltyp für eine Verbindung.',0),
    104 6032 => array('Interner Fehler: Unbekannter Pfadtyp (=%d) für eine Verbindung.',1),
     1016028 => array('Die eingegebene Höhe (%d) fÃŒr GanttBar ist nicht im zulÀssigen Bereich.',1),
     1026029 => array('Der Offset fÃŒr die vertikale Linie muss im Bereich [0,1] sein.',0),
     1036030 => array('Unbekannte Pfeilrichtung fÃŒr eine Verbindung.',0),
     1046031 => array('Unbekannter Pfeiltyp fÃŒr eine Verbindung.',0),
     1056032 => array('Interner Fehler: Unbekannter Pfadtyp (=%d) fÃŒr eine Verbindung.',1),
     1066033 => array('Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)',0),
    105107
    106108/*
     
    114116*/
    115117
    116 8001 => array('Der Mix-Wert für das Icon muss zwischen 0 und 100 sein.',0),
    117 8002 => array('Die Ankerposition für Icons muss entweder "top", "bottom", "left", "right" oder "center" sein.',0),
    118 8003 => array('Es ist nicht möglich, gleichzeitig ein Bild und eine Landesflagge für dasselbe Icon zu definieren',0),
    119 8004 => array('Wenn Du Landesflaggen benutzen willst, musst Du die Datei "jpgraph_flags.php" hinzufügen (per include).',0),
     1188001 => array('Der Mix-Wert fÃŒr das Icon muss zwischen 0 und 100 sein.',0),
     1198002 => array('Die Ankerposition fÃŒr Icons muss entweder "top", "bottom", "left", "right" oder "center" sein.',0),
     1208003 => array('Es ist nicht möglich, gleichzeitig ein Bild und eine Landesflagge fÃŒr dasselbe Icon zu definieren',0),
     1218004 => array('Wenn Du Landesflaggen benutzen willst, musst Du die Datei "jpgraph_flags.php" hinzufÃŒgen (per include).',0),
    120122
    121123/*
     
    123125*/
    124126
    125 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),
     1279001 => 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),
    126128
    127129/*
     
    130132
    13113310001 => array('Die Methode LinePlot::SetFilled() sollte nicht mehr benutzt werden. Benutze lieber SetFillColor()',0),
    132 10002 => array('Der Plot ist zu kompliziert für FastLineStroke. Benutze lieber den StandardStroke()',0),
     13410002 => array('Der Plot ist zu kompliziert fÃŒr FastLineStroke. Benutze lieber den StandardStroke()',0),
    13313510003 => array('Each plot in an accumulated lineplot must have the same number of data points.',0),
    134136/*
     
    137139
    13814011001 => array('Deine Daten enthalten nicht-numerische Werte.',0),
    139 11002 => array('Negative Werte können nicht für logarithmische Achsen verwendet werden.',0),
     14111002 => array('Negative Werte können nicht fÃŒr logarithmische Achsen verwendet werden.',0),
    14014211003 => array('Deine Daten enthalten nicht-numerische Werte.',0),
    141 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),
    142 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),
     14311004 => 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),
     14411005 => 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),
    143145
    144146/*
     
    146148*/
    147149
    148 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),
    149 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),
    150 12003 => array('Unbekannte Dateierweiterung (%s) in MGraph::SetBackgroundImage() für Dateiname: %s',2),
    151 12004 => array('Das Bildformat des Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstützt. ',1),
     15012001 => 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),
     15112002 => 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),
     15212003 => array('Unbekannte Dateierweiterung (%s) in MGraph::SetBackgroundImage() fÃŒr Dateiname: %s',2),
     15312004 => array('Das Bildformat des Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstÃŒtzt. ',1),
    15215412005 => array('Das Hintergrundbild kann nicht gelesen werden: %s',1),
    153 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),
    154 12007 => array('Das Argument für MGraph::Add() ist nicht gültig für GD.',0),
    155 12008 => array('Deine PHP- (und GD-lib-) Installation scheint keine bekannten Bildformate zu unterstützen.',0),
    156 12009 => array('Deine PHP-Installation unterstützt das gewählte Bildformat nicht: %s',1),
    157 12010 => array('Es konnte kein Bild als Datei %s erzeugt werden. Überprüfe, ob Du die entsprechenden Schreibrechte im aktuellen Verzeichnis hast.',1),
    158 12011 => array('Es konnte kein Truecolor-Bild erzeugt werden. Überprüfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0),
    159 12012 => array('Es konnte kein Bild erzeugt werden. Überprüfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0),
     15512006 => array('Es wurden ungÃŒltige Größen fÃŒr Breite oder Höhe beim Erstellen des Bildes angegeben, (Breite=%d, Höhe=%d)',2),
     15612007 => array('Das Argument fÃŒr MGraph::Add() ist nicht gÃŒltig fÃŒr GD.',0),
     15712008 => array('Deine PHP- (und GD-lib-) Installation scheint keine bekannten Bildformate zu unterstÃŒtzen.',0),
     15812009 => array('Deine PHP-Installation unterstÃŒtzt das gewÀhlte Bildformat nicht: %s',1),
     15912010 => array('Es konnte kein Bild als Datei %s erzeugt werden. ÜberprÃŒfe, ob Du die entsprechenden Schreibrechte im aktuellen Verzeichnis hast.',1),
     16012011 => array('Es konnte kein Truecolor-Bild erzeugt werden. ÜberprÃŒfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0),
     16112012 => array('Es konnte kein Bild erzeugt werden. ÜberprÃŒfe, ob Du wirklich die GD2-Bibliothek installiert hast.',0),
    160162
    161163/*
     
    163165*/
    164166
    165 14001 => array('Pie3D::ShowBorder(). Missbilligte Funktion. Benutze Pie3D::SetEdge(), um die Ecken der Tortenstücke zu kontrollieren.',0),
     16714001 => array('Pie3D::ShowBorder(). Missbilligte Funktion. Benutze Pie3D::SetEdge(), um die Ecken der TortenstÃŒcke zu kontrollieren.',0),
    16616814002 => array('PiePlot3D::SetAngle() 3D-Torten-Projektionswinkel muss zwischen 5 und 85 Grad sein.',0),
    16716914003 => array('Interne Festlegung schlug fehl. Pie3D::Pie3DSlice',0),
    168 14004 => array('Tortenstück-Startwinkel muss zwischen 0 und 360 Grad sein.',0),
    169 14005 => array('Pie3D Interner Fehler: Versuch, zweimal zu umhüllen bei der Suche nach dem Startindex.',0,),
    170 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),
    171 14007 => array('Die Breite für das 3D-Tortendiagramm ist 0. Gib eine Breite > 0 an.',0),
     17014004 => array('TortenstÃŒck-Startwinkel muss zwischen 0 und 360 Grad sein.',0),
     17114005 => array('Pie3D Interner Fehler: Versuch, zweimal zu umhÃŒllen bei der Suche nach dem Startindex.',0,),
     17214006 => 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),
     17314007 => array('Die Breite fÃŒr das 3D-Tortendiagramm ist 0. Gib eine Breite > 0 an.',0),
    172174
    173175/*
     
    176178
    17717915001 => array('PiePLot::SetTheme() Unbekannter Stil: %s',1),
    178 15002 => array('Argument für PiePlot::ExplodeSlice() muss ein Integer-Wert sein',0),
    179 15003 => array('Argument für PiePlot::Explode() muss ein Vektor mit Integer-Werten sein.',0),
    180 15004 => array('Tortenstück-Startwinkel muss zwischen 0 und 360 Grad sein.',0),
     18015002 => array('Argument fÃŒr PiePlot::ExplodeSlice() muss ein Integer-Wert sein',0),
     18115003 => array('Argument fÃŒr PiePlot::Explode() muss ein Vektor mit Integer-Werten sein.',0),
     18215004 => array('TortenstÃŒck-Startwinkel muss zwischen 0 und 360 Grad sein.',0),
    18118315005 => array('PiePlot::SetFont() sollte nicht mehr verwendet werden. Benutze stattdessen PiePlot->value->SetFont().',0),
    182 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),
     18415006 => 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),
    18318515007 => array('PiePlot::SetFontColor() sollte nicht mehr verwendet werden. Benutze stattdessen PiePlot->value->SetColor()..',0),
    184 15008 => array('PiePlot::SetLabelType() der Typ für Tortendiagramme muss entweder 0 or 1 sein (nicht %d).',1),
    185 15009 => array('Ungültiges Tortendiagramm. Die Summe aller Daten ist Null.',0),
     18615008 => array('PiePlot::SetLabelType() der Typ fÃŒr Tortendiagramme muss entweder 0 or 1 sein (nicht %d).',1),
     18715009 => array('UngÃŒltiges Tortendiagramm. Die Summe aller Daten ist Null.',0),
    18618815010 => array('Die Summe aller Daten ist Null.',0),
    187 15011 => array('Um Bildtransformationen benutzen zu können, muss die Datei jpgraph_imgtrans.php eingefügt werden (per include).',0),
     18915011 => array('Um Bildtransformationen benutzen zu können, muss die Datei jpgraph_imgtrans.php eingefÃŒgt werden (per include).',0), // @todo translate into German
     19015012 => array('PiePlot::SetTheme() is no longer recommended. Use PieGraph::SetTheme()',0),
    188191
    189192/*
     
    191194*/
    192195
    193 16001 => array('Die Dichte für das Pattern muss zwischen 1 und 100 sein. (Du hast %f eingegeben)',1),
    194 16002 => array('Es wurde keine Position für das Pattern angegeben.',0),
     19616001 => array('Die Dichte fÃŒr das Pattern muss zwischen 1 und 100 sein. (Du hast %f eingegeben)',1),
     19716002 => array('Es wurde keine Position fÃŒr das Pattern angegeben.',0),
    19519816003 => array('Unbekannte Pattern-Definition (%d)',0),
    196 16004 => array('Der Mindeswert für das PlotBand ist größer als der Maximalwert. Bitte korrigiere dies!',0),
     19916004 => array('Der Mindeswert fÃŒr das PlotBand ist größer als der Maximalwert. Bitte korrigiere dies!',0),
    197200
    198201
     
    201204*/
    202205
    203 17001 => array('PolarPlots müssen eine gerade Anzahl von Datenpunkten haben. Jeder Datenpunkt ist ein Tupel (Winkel, Radius).',0),
    204 17002 => array('Unbekannte Ausrichtung für X-Achsen-Titel. (%s)',1),
    205 //17003 => array('Set90AndMargin() wird für PolarGraph nicht unterstützt.',0),
    206 17004 => array('Unbekannter Achsentyp für PolarGraph. Er muss entweder \'lin\' oder \'log\' sein.',0),
     20617001 => array('PolarPlots mÃŒssen eine gerade Anzahl von Datenpunkten haben. Jeder Datenpunkt ist ein Tupel (Winkel, Radius).',0),
     20717002 => array('Unbekannte Ausrichtung fÃŒr X-Achsen-Titel. (%s)',1),
     208//17003 => array('Set90AndMargin() wird fÃŒr PolarGraph nicht unterstÃŒtzt.',0),
     20917004 => array('Unbekannter Achsentyp fÃŒr PolarGraph. Er muss entweder \'lin\' oder \'log\' sein.',0),
    207210
    208211/*
     
    210213*/
    211214
    212 18001 => array('ClientSideImageMaps werden für RadarPlots nicht unterstützt.',0),
     21518001 => array('ClientSideImageMaps werden fÃŒr RadarPlots nicht unterstÃŒtzt.',0),
    21321618002 => array('RadarGraph::SupressTickMarks() sollte nicht mehr verwendet werden. Benutze stattdessen HideTickMarks().',0),
    214 18003 => array('Ungültiger Achsentyp für RadarPlot (%s). Er muss entweder \'lin\' oder \'log\' sein.',1),
    215 18004 => array('Die RadarPlot-Größe muss zwischen 0.1 und 1 sein. (Dein Wert=%f)',1),
    216 18005 => array('RadarPlot: nicht unterstützte Tick-Dichte: %d',1),
     21718003 => array('UngÃŒltiger Achsentyp fÃŒr RadarPlot (%s). Er muss entweder \'lin\' oder \'log\' sein.',1),
     21818004 => array('Die RadarPlot-Größe muss zwischen 0.1 und 1 sein. (Dein Wert=%f)',1),
     21918005 => array('RadarPlot: nicht unterstÃŒtzte Tick-Dichte: %d',1),
    21722018006 => array('Minimum Daten %f (RadarPlots sollten nur verwendet werden, wenn alle Datenpunkte einen Wert > 0 haben).',1),
    21822118007 => array('Die Anzahl der Titel entspricht nicht der Anzahl der Datenpunkte.',0),
     
    224227
    22522819001 => array('Spline: Anzahl der X- und Y-Koordinaten muss gleich sein.',0),
    226 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),
     22919002 => 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),
    22723019003 => array('Bezier: Anzahl der X- und Y-Koordinaten muss gleich sein.',0),
    228231
     
    231234*/
    232235
    233 20001 => array('Fieldplots müssen die gleiche Anzahl von X und Y Datenpunkten haben.',0),
    234 20002 => array('Bei Fieldplots muss ein Winkel für jeden X und Y Datenpunkt angegeben werden.',0),
    235 20003 => array('Scatterplots müssen die gleiche Anzahl von X- und Y-Datenpunkten haben.',0),
     23620001 => array('Fieldplots mÃŒssen die gleiche Anzahl von X und Y Datenpunkten haben.',0),
     23720002 => array('Bei Fieldplots muss ein Winkel fÃŒr jeden X und Y Datenpunkt angegeben werden.',0),
     23820003 => array('Scatterplots mÃŒssen die gleiche Anzahl von X- und Y-Datenpunkten haben.',0),
    236239
    237240/*
     
    239242*/
    240243
    241 21001 => array('Die Anzahl der Datenwerte für Stock-Charts müssen ein Mehrfaches von %d Datenpunkten sein.',1),
     24421001 => array('Die Anzahl der Datenwerte fÃŒr Stock-Charts mÃŒssen ein Mehrfaches von %d Datenpunkten sein.',1),
    242245
    243246/*
     
    246249
    24725023001 => array('Der Marker "%s" existiert nicht in der Farbe: %d',2),
    248 23002 => array('Der Farb-Index ist zu hoch für den Marker "%s"',1),
     25123002 => array('Der Farb-Index ist zu hoch fÃŒr den Marker "%s"',1),
    24925223003 => array('Ein Dateiname muss angegeben werden, wenn Du den Marker-Typ auf MARK_IMG setzt.',0),
    250253
     
    25625924002 => array('FuncGenerator : Syntax-Fehler in der Funktionsdefinition ',0),
    25726024003 => array('DateScaleUtils: Unknown tick type specified in call to GetTicks()',0),
    258 
     26124004 => array('ReadCSV2: Die anzahl der spalten fehler in %s reihe %d',2),
    259262/*
    260263**  jpgraph
    261264*/
    262265
    263 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),
    264 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),
     26625001 => 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),
     26725002 => 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),
    26526825003 => array('Genereller PHP Fehler : Bei %s:%d : %s',3),
    26626925004 => array('Genereller PHP Fehler : %s ',1),
    26727025005 => 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),
    268 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),
    269 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),
    270 25008 => array('Die Bild-Breite und Höhe in Graph::Graph() müssen numerisch sein',0),
     27125006 => 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),
     27225007 => 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),
     27325008 => array('Die Bild-Breite und Höhe in Graph::Graph() mÃŒssen numerisch sein',0),
    27127425009 => array('Die Skalierung der Achsen muss angegeben werden mit Graph::SetScale()',0),
    272275
    273 25010 => array('Graph::Add() Du hast versucht, einen leeren Plot zum Graph hinzuzufügen.',0),
    274 25011 => array('Graph::AddY2() Du hast versucht, einen leeren Plot zum Graph hinzuzufügen.',0),
    275 25012 => array('Graph::AddYN() Du hast versucht, einen leeren Plot zum Graph hinzuzufügen.',0),
    276 25013 => array('Es können nur Standard-Plots zu multiplen Y-Achsen hinzugefügt werden',0),
    277 25014 => array('Graph::AddText() Du hast versucht, einen leeren Text zum Graph hinzuzufügen.',0),
    278 25015 => array('Graph::AddLine() Du hast versucht, eine leere Linie zum Graph hinzuzufügen.',0),
    279 25016 => array('Graph::AddBand() Du hast versucht, ein leeres Band zum Graph hinzuzufügen.',0),
    280 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),
    281 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),
    282 25019 => array('Unbekannte Dateinamenerweiterung (%s) in Graph::SetBackgroundImage() für Dateiname: "%s"',2),
    283 
    284 25020 => array('Graph::SetScale(): Dar Maximalwert muss größer sein als der Mindestwert.',0),
    285 25021 => array('Unbekannte Achsendefinition für die Y-Achse. (%s)',1),
    286 25022 => array('Unbekannte Achsendefinition für die X-Achse. (%s)',1),
    287 25023 => array('Nicht unterstützter Y2-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1),
    288 25024 => array('Nicht unterstützter X-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1),
    289 25025 => array('Nicht unterstützte Tick-Dichte: %d',1),
    290 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),
    291 25027 => array('Kann cached CSIM "%s" zum Lesen nicht öffnen.',1),
    292 25028 => array('Apache/PHP hat keine Schreibrechte, in das CSIM-Cache-Verzeichnis (%s) zu schreiben. Überprüfe die Rechte.',1),
    293 25029 => array('Kann nicht in das CSIM "%s" schreiben. Überprüfe die Schreibrechte und den freien Speicherplatz.',1),
    294 
    295 25030 => array('Fehlender Skriptname für StrokeCSIM(). Der Name des aktuellen Skriptes muss als erster Parameter von StrokeCSIM() angegeben werden.',0),
     27625010 => array('Graph::Add() Du hast versucht, einen leeren Plot zum Graph hinzuzufÃŒgen.',0),
     27725011 => array('Graph::AddY2() Du hast versucht, einen leeren Plot zum Graph hinzuzufÃŒgen.',0),
     27825012 => array('Graph::AddYN() Du hast versucht, einen leeren Plot zum Graph hinzuzufÃŒgen.',0),
     27925013 => array('Es können nur Standard-Plots zu multiplen Y-Achsen hinzugefÃŒgt werden',0),
     28025014 => array('Graph::AddText() Du hast versucht, einen leeren Text zum Graph hinzuzufÃŒgen.',0),
     28125015 => array('Graph::AddLine() Du hast versucht, eine leere Linie zum Graph hinzuzufÃŒgen.',0),
     28225016 => array('Graph::AddBand() Du hast versucht, ein leeres Band zum Graph hinzuzufÃŒgen.',0),
     28325017 => 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),
     28425018 => 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),
     28525019 => array('Unbekannte Dateinamenerweiterung (%s) in Graph::SetBackgroundImage() fÃŒr Dateiname: "%s"',2),
     286
     28725020 => array('Graph::SetScale(): Dar Maximalwert muss größer sein als der Mindestwert.',0),
     28825021 => array('Unbekannte Achsendefinition fÃŒr die Y-Achse. (%s)',1),
     28925022 => array('Unbekannte Achsendefinition fÃŒr die X-Achse. (%s)',1),
     29025023 => array('Nicht unterstÃŒtzter Y2-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1),
     29125024 => array('Nicht unterstÃŒtzter X-Achsentyp: "%s" muss einer von (lin,log,int) sein.',1),
     29225025 => array('Nicht unterstÃŒtzte Tick-Dichte: %d',1),
     29325026 => 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),
     29425027 => array('Kann cached CSIM "%s" zum Lesen nicht öffnen.',1),
     29525028 => array('Apache/PHP hat keine Schreibrechte, in das CSIM-Cache-Verzeichnis (%s) zu schreiben. ÜberprÃŒfe die Rechte.',1),
     29625029 => array('Kann nicht in das CSIM "%s" schreiben. ÜberprÃŒfe die Schreibrechte und den freien Speicherplatz.',1),
     297
     29825030 => array('Fehlender Skriptname fÃŒr StrokeCSIM(). Der Name des aktuellen Skriptes muss als erster Parameter von StrokeCSIM() angegeben werden.',0),
    29629925031 => array('Der Achsentyp muss mittels Graph::SetScale() angegeben werden.',0),
    297 25032 => array('Es existieren keine Plots für die Y-Achse nbr:%d',1),
     30025032 => array('Es existieren keine Plots fÃŒr die Y-Achse nbr:%d',1),
    29830125033 => array('',0),
    29930225034 => array('Undefinierte X-Achse kann nicht gezeichnet werden. Es wurden keine Plots definiert.',0),
    300 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),
     30325035 => 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),
    30130425036 => array('Unbekannter Achsentyp AxisStyle() : %s',1),
    302 25037 => array('Das Bildformat Deines Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstützt. ',1),
     30525037 => array('Das Bildformat Deines Hintergrundbildes (%s) wird von Deiner System-Konfiguration nicht unterstÃŒtzt. ',1),
    30330625038 => array('Das Hintergrundbild scheint von einem anderen Typ (unterschiedliche Dateierweiterung) zu sein als der angegebene Typ. Angegebenen: %s; Datei: %s',2),
    30430725039 => array('Hintergrundbild kann nicht gelesen werden: "%s"',1),
    305308
    306 25040 => array('Es ist nicht möglich, sowohl ein Hintergrundbild als auch eine Hintergrund-Landesflagge anzugeben.',0),
    307 25041 => array('Um Landesflaggen als Hintergrund benutzen zu können, muss die Datei "jpgraph_flags.php" eingefügt werden (per include).',0),
     30925040 => array('Es ist nicht möglich, sowohl ein Hintergrundbild als auch eine Hintergrund-Landesflagge anzugeben.',0),
     31025041 => array('Um Landesflaggen als Hintergrund benutzen zu können, muss die Datei "jpgraph_flags.php" eingefÃŒgt werden (per include).',0),
    30831125042 => array('Unbekanntes Hintergrundbild-Layout',0),
    30931225043 => array('Unbekannter Titelhintergrund-Stil.',0),
    310 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),
    311 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),
     31325044 => 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),
     31425045 => 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),
    31231525046 => 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),
    313 25047 => array('Stil %s ist nicht verfügbar für Schriftfamilie %s',2),
     31625047 => array('Stil %s ist nicht verfÃŒgbar fÃŒr Schriftfamilie %s',2),
    31431725048 => array('Unbekannte Schriftstildefinition [%s].',1),
    31531825049 => array('Schriftdatei "%s" ist nicht lesbar oder existiert nicht.',1),
    316319
    317 25050 => array('Erstes Argument für Text::Text() muss ein String sein.',0),
    318 25051 => array('Ungültige Richtung angegeben für Text.',0),
    319 25052 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte vertikale Ausrichtung für Text.',0),
    320 25053 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte horizontale Ausrichtung für Text.',0),
     32025050 => array('Erstes Argument fÃŒr Text::Text() muss ein String sein.',0),
     32125051 => array('UngÃŒltige Richtung angegeben fÃŒr Text.',0),
     32225052 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte vertikale Ausrichtung fÃŒr Text.',0),
     32325053 => array('PANIK: Interner Fehler in SuperScript::Stroke(). Unbekannte horizontale Ausrichtung fÃŒr Text.',0),
    32132425054 => array('Interner Fehler: Unbekannte Grid-Achse %s',1),
    32232525055 => array('Axis::SetTickDirection() sollte nicht mehr verwendet werden. Benutze stattdessen Axis::SetTickSide().',0),
     
    32632925059 => array('SetLabelPos() sollte nicht mehr verwendet werden. Benutze stattdessen Axis::SetLabelSide().',0),
    327330
    328 25060 => array('Unbekannte Ausrichtung angegeben für X-Achsentitel (%s).',1),
    329 25061 => array('Unbekannte Ausrichtung angegeben für Y-Achsentitel (%s).',1),
    330 25062 => array('Label unter einem Winkel werden für die Y-Achse nicht unterstützt.',0),
     33125060 => array('Unbekannte Ausrichtung angegeben fÃŒr X-Achsentitel (%s).',1),
     33225061 => array('Unbekannte Ausrichtung angegeben fÃŒr Y-Achsentitel (%s).',1),
     33325062 => array('Label unter einem Winkel werden fÃŒr die Y-Achse nicht unterstÃŒtzt.',0),
    33133425063 => array('Ticks::SetPrecision() sollte nicht mehr verwendet werden. Benutze stattdessen Ticks::SetLabelFormat() (oder Ticks::SetFormatCallback()).',0),
    332 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),
    333 25065 => array('Tick-Positionen müssen als array() angegeben werden',0),
     33525064 => 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),
     33625065 => array('Tick-Positionen mÃŒssen als array() angegeben werden',0),
    33433725066 => array('Wenn die Tick-Positionen und -Label von Hand eingegeben werden, muss die Anzahl der Ticks und der Label gleich sein.',0),
    335 25067 => array('Deine von Hand eingegebene Achse und Ticks sind nicht korrekt. Die Skala scheint zu klein zu sein für den Tickabstand.',0),
    336 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),
    337 25069 => array('Grace muss größer sein als 0',0),
     33825067 => array('Deine von Hand eingegebene Achse und Ticks sind nicht korrekt. Die Skala scheint zu klein zu sein fÃŒr den Tickabstand.',0),
     33925068 => 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),
     34025069 => array('Grace muss größer sein als 0',0),
    338341
    33934225070 => array('Deine Daten enthalten nicht-numerische Werte.',0),
    340 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),
    341 25072 => array('Du hast mit SetAutoMax() einen Maximalwert angegeben, der kleiner ist als der Minimalwert der Achse. Dies ist nicht möglich.',0),
    342 25073 => array('Interner Fehler. Der Integer-Skalierungs-Algorithmus-Vergleich ist außerhalb der Grenzen  (r=%f).',1),
    343 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),
    344 25075 => array('Die automatischen Ticks können nicht gesetzt werden, weil min==max.',0),
    345 25077 => array('Einstellfaktor für die Farbe muss größer sein als 0',0),
     34325071 => 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),
     34425072 => array('Du hast mit SetAutoMax() einen Maximalwert angegeben, der kleiner ist als der Minimalwert der Achse. Dies ist nicht möglich.',0),
     34525073 => array('Interner Fehler. Der Integer-Skalierungs-Algorithmus-Vergleich ist außerhalb der Grenzen  (r=%f).',1),
     34625074 => 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),
     34725075 => array('Die automatischen Ticks können nicht gesetzt werden, weil min==max.',0),
     34825077 => array('Einstellfaktor fÃŒr die Farbe muss größer sein als 0',0),
    34634925078 => array('Unbekannte Farbe: %s',1),
    347 25079 => array('Unbekannte Farbdefinition: %s, Größe=%d',2),
    348 
    349 25080 => array('Der Alpha-Parameter für Farben muss zwischen 0.0 und 1.0 liegen.',0),
    350 25081 => array('Das ausgewählte Grafikformat wird entweder nicht unterstützt oder ist unbekannt [%s]',1),
    351 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),
    352 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),
    353 25084 => array('Fehler beim Erstellen eines temporären GD-Canvas. Möglicherweise liegt ein Arbeitsspeicherproblem vor.',0),
    354 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),
    355 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),
    356 25087 => array('Diese PHP-Version wurde ohne TTF-Unterstützung konfiguriert. PHP muss mit TTF-Unterstützung neu kompiliert und installiert werden.',0),
    357 25088 => array('Die GD-Schriftunterstützung wurde falsch konfiguriert. Der Aufruf von imagefontwidth() ist fehlerhaft.',0),
    358 25089 => array('Die GD-Schriftunterstützung wurde falsch konfiguriert. Der Aufruf von imagefontheight() ist fehlerhaft.',0),
     35025079 => array('Unbekannte Farbdefinition: %s, Größe=%d',2),
     351
     35225080 => array('Der Alpha-Parameter fÃŒr Farben muss zwischen 0.0 und 1.0 liegen.',0),
     35325081 => array('Das ausgewÀhlte Grafikformat wird entweder nicht unterstÃŒtzt oder ist unbekannt [%s]',1),
     35425082 => array('Es wurden ungÃŒltige Größen fÃŒr Breite und Höhe beim Erstellen des Bildes definiert (Breite=%d, Höhe=%d).',2),
     35525083 => 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),
     35625084 => array('Fehler beim Erstellen eines temporÀren GD-Canvas. Möglicherweise liegt ein Arbeitsspeicherproblem vor.',0),
     35725085 => 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),
     35825086 => 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),
     35925087 => array('Diese PHP-Version wurde ohne TTF-UnterstÃŒtzung konfiguriert. PHP muss mit TTF-UnterstÃŒtzung neu kompiliert und installiert werden.',0),
     36025088 => array('Die GD-SchriftunterstÃŒtzung wurde falsch konfiguriert. Der Aufruf von imagefontwidth() ist fehlerhaft.',0),
     36125089 => array('Die GD-SchriftunterstÃŒtzung wurde falsch konfiguriert. Der Aufruf von imagefontheight() ist fehlerhaft.',0),
    359362
    36036325090 => array('Unbekannte Richtung angegeben im Aufruf von StrokeBoxedText() [%s].',1),
    361 25091 => array('Die interne Schrift untestützt das Schreiben von Text in einem beliebigen Winkel nicht. Benutze stattdessen TTF-Schriften.',0),
    362 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),
     36425091 => array('Die interne Schrift untestÃŒtzt das Schreiben von Text in einem beliebigen Winkel nicht. Benutze stattdessen TTF-Schriften.',0),
     36525092 => 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),
    36336625093 => 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),
    36436725094 => array('Die Textrichtung muss in einem Winkel zwischen 0 und 90 engegeben werden.',0),
    36536825095 => array('Unbekannte Schriftfamilien-Definition. ',0),
    366 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),
     36925096 => 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),
    36737025097 => array('Eine Farbe wurde als leerer String im Aufruf von PushColor() angegegeben.',0),
    36837125098 => array('Negativer Farbindex. Unpassender Aufruf von PopColor().',0),
    369 25099 => array('Die Parameter für Helligkeit und Kontrast sind außerhalb des zulässigen Bereichs [-1,1]',0),
     37225099 => array('Die Parameter fÃŒr Helligkeit und Kontrast sind außerhalb des zulÀssigen Bereichs [-1,1]',0),
    370373
    37137425100 => 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),
    372 25101 => array('Ungültiges numerisches Argument für SetLineStyle(): (%d)',1),
    373 25102 => array('Ungültiges String-Argument für SetLineStyle(): %s',1),
    374 25103 => array('Ungültiges Argument für SetLineStyle %s',1),
     37525101 => array('UngÃŒltiges numerisches Argument fÃŒr SetLineStyle(): (%d)',1),
     37625102 => array('UngÃŒltiges String-Argument fÃŒr SetLineStyle(): %s',1),
     37725103 => array('UngÃŒltiges Argument fÃŒr SetLineStyle %s',1),
    37537825104 => array('Unbekannter Linientyp: %s',1),
    376 25105 => array('Es wurden NULL-Daten für ein gefülltes Polygon angegeben. Sorge dafür, dass keine NULL-Daten angegeben werden.',0),
    377 25106 => array('Image::FillToBorder : es können keine weiteren Farben zugewiesen werden.',0),
    378 25107 => array('In Datei "%s" kann nicht geschrieben werden. Überprüfe die aktuellen Schreibrechte.',1),
    379 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),
    380 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),
    381 
    382 25110 => array('Dein PHP-Installation unterstützt das gewählte Grafikformat nicht: %s',1),
    383 25111 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1),
     37925105 => array('Es wurden NULL-Daten fÃŒr ein gefÃŒlltes Polygon angegeben. Sorge dafÃŒr, dass keine NULL-Daten angegeben werden.',0),
     38025106 => array('Image::FillToBorder : es können keine weiteren Farben zugewiesen werden.',0),
     38125107 => array('In Datei "%s" kann nicht geschrieben werden. ÜberprÃŒfe die aktuellen Schreibrechte.',1),
     38225108 => 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),
     38325109 => 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
     38525110 => array('Dein PHP-Installation unterstÃŒtzt das gewÀhlte Grafikformat nicht: %s',1),
     38625111 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1),
    38438725112 => array('Das Datum der gecacheten Datei (%s) liegt in der Zukunft.',1),
    385 25113 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1),
    386 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),
    387 25115 => array('Berechtigung für gecachetes Bild %s kann nicht gesetzt werden. Problem mit den Rechten?',1),
    388 25116 => array('Datei kann nicht aus dem Cache %s geöffnet werden',1),
    389 25117 => array('Gecachetes Bild %s kann nicht zum Lesen geöffnet werden.',1),
     38825113 => array('Das gecachete Bild %s kann nicht gelöscht werden. Problem mit den Rechten?',1),
     38925114 => 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),
     39025115 => array('Berechtigung fÃŒr gecachetes Bild %s kann nicht gesetzt werden. Problem mit den Rechten?',1),
     39125116 => array('Datei kann nicht aus dem Cache %s geöffnet werden',1),
     39225117 => array('Gecachetes Bild %s kann nicht zum Lesen geöffnet werden.',1),
    39039325118 => array('Verzeichnis %s kann nicht angelegt werden. Versichere Dich, dass PHP die Schreibrechte in diesem Verzeichnis hat.',1),
    391 25119 => array('Rechte für Datei %s können nicht gesetzt werden. Problem mit den Rechten?',1),
    392 
    393 25120 => array('Die Position für die Legende muss als Prozentwert im Bereich 0-1 angegeben werden.',0),
    394 25121 => array('Eine leerer Datenvektor wurde für den Plot eingegeben. Es muss wenigstens ein Datenpunkt vorliegen.',0),
     39425119 => array('Rechte fÃŒr Datei %s können nicht gesetzt werden. Problem mit den Rechten?',1),
     395
     39625120 => array('Die Position fÃŒr die Legende muss als Prozentwert im Bereich 0-1 angegeben werden.',0),
     39725121 => array('Eine leerer Datenvektor wurde fÃŒr den Plot eingegeben. Es muss wenigstens ein Datenpunkt vorliegen.',0),
    39539825122 => array('Stroke() muss als Subklasse der Klasse Plot definiert sein.',0),
    39639925123 => array('Du kannst keine Text-X-Achse mit X-Koordinaten verwenden. Benutze stattdessen eine "int" oder "lin" Achse.',0),
    397 25124 => array('Der Eingabedatenvektor mus aufeinanderfolgende Werte von 0 aufwärts beinhalten. Der angegebene Y-Vektor beginnt mit leeren Werten (NULL).',0),
    398 25125 => array('Ungültige Richtung für statische Linie.',0),
    399 25126 => array('Es kann kein TrueColor-Bild erzeugt werden. Überprüfe, ob die GD2-Bibliothek und PHP korrekt aufgesetzt wurden.',0),
     40025124 => array('Der Eingabedatenvektor mus aufeinanderfolgende Werte von 0 aufwÀrts beinhalten. Der angegebene Y-Vektor beginnt mit leeren Werten (NULL).',0),
     40125125 => array('UngÃŒltige Richtung fÃŒr statische Linie.',0),
     40225126 => array('Es kann kein TrueColor-Bild erzeugt werden. ÜberprÃŒfe, ob die GD2-Bibliothek und PHP korrekt aufgesetzt wurden.',0),
    40040325127 => 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),
    40140425128 => 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),
    40240525129 => array('Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.',0),
     40625130 => 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
     40825131 => array('StrokeBoxedText2() only supports TTF fonts and not built-in bitmap fonts.',0),
     40925132 => array('Undefined property %s.',1), // @todo translate
     41025133 => array('Use Graph::SetTheme() after Graph::SetScale().',0), // @todo translate
     411
     412/*
     413**  jpgraph_led
     414*/
     415
     41625500 => 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
    403419/*
    404420**---------------------------------------------------------------------------------------------
     
    411427*/
    412428
    413 27001 => array('GTextTable: Ungültiges Argument für Set(). Das Array-Argument muss 2-- dimensional sein.',0),
    414 27002 => array('GTextTable: Ungültiges Argument für Set()',0),
    415 27003 => array('GTextTable: Falsche Anzahl von Argumenten für GTextTable::SetColor()',0),
    416 27004 => array('GTextTable: Angegebener Zellenbereich, der verschmolzen werden soll, ist ungültig.',0),
    417 27005 => array('GTextTable: Bereits verschmolzene Zellen im Bereich (%d,%d) bis (%d,%d) können nicht ein weiteres Mal verschmolzen werden.',4),
    418 27006 => array('GTextTable: Spalten-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1),
    419 27007 => array('GTextTable: Zeilen-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1),
    420 27008 => array('GTextTable: Spalten- und Zeilengröße müssen zu den Dimensionen der Tabelle passen.',0),
     42927001 => array('GTextTable: UngÃŒltiges Argument fÃŒr Set(). Das Array-Argument muss 2-- dimensional sein.',0),
     43027002 => array('GTextTable: UngÃŒltiges Argument fÃŒr Set()',0),
     43127003 => array('GTextTable: Falsche Anzahl von Argumenten fÃŒr GTextTable::SetColor()',0),
     43227004 => array('GTextTable: Angegebener Zellenbereich, der verschmolzen werden soll, ist ungÃŒltig.',0),
     43327005 => array('GTextTable: Bereits verschmolzene Zellen im Bereich (%d,%d) bis (%d,%d) können nicht ein weiteres Mal verschmolzen werden.',4),
     43427006 => array('GTextTable: Spalten-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1),
     43527007 => array('GTextTable: Zeilen-Argument = %d liegt außerhalb der festgelegten Tabellengröße.',1),
     43627008 => array('GTextTable: Spalten- und Zeilengröße mÃŒssen zu den Dimensionen der Tabelle passen.',0),
    42143727009 => array('GTextTable: Die Anzahl der Tabellenspalten oder -zeilen ist 0. Versichere Dich, dass die Methoden Init() oder Set() aufgerufen werden.',0),
    42243827010 => array('GTextTable: Es wurde keine Ausrichtung beim Aufruf von SetAlign() angegeben.',0),
    42343927011 => array('GTextTable: Es wurde eine unbekannte Ausrichtung beim Aufruf von SetAlign() abgegeben. Horizontal=%s, Vertikal=%s',2),
    424 27012 => array('GTextTable: Interner Fehler. Es wurde ein ungültiges Argument festgeleget %s',1),
    425 27013 => array('GTextTable: Das Argument für FormatNumber() muss ein String sein.',0),
     44027012 => array('GTextTable: Interner Fehler. Es wurde ein ungÃŒltiges Argument festgeleget %s',1),
     44127013 => array('GTextTable: Das Argument fÃŒr FormatNumber() muss ein String sein.',0),
    42644227014 => array('GTextTable: Die Tabelle wurde weder mit einem Aufruf von Set() noch von Init() initialisiert.',0),
    42744327015 => array('GTextTable: Der Zellenbildbedingungstyp muss entweder TIMG_WIDTH oder TIMG_HEIGHT sein.',0),
     
    431447*/
    432448
    433 22001 => array('Die Gesamtsumme der prozentualen Anteile aller Windrosenarme darf 100%% nicht überschreiten!\n(Aktuell max: %d)',1),
    434 22002 => array('Das Bild ist zu klein für eine Skala. Bitte vergrößere das Bild.',0),
    435 22004 => array('Die Etikettendefinition für Windrosenrichtungen müssen 16 Werte haben (eine für jede Kompassrichtung).',0),
    436 22005 => array('Der Linientyp für radiale Linien muss einer von ("solid","dotted","dashed","longdashed") sein.',0),
    437 22006 => array('Es wurde ein ungültiger Windrosentyp angegeben.',0),
    438 22007 => array('Es wurden zu wenig Werte für die Bereichslegende angegeben.',0),
     44922001 => array('Die Gesamtsumme der prozentualen Anteile aller Windrosenarme darf 100%% nicht ÃŒberschreiten!\n(Aktuell max: %d)',1),
     45022002 => array('Das Bild ist zu klein fÃŒr eine Skala. Bitte vergrößere das Bild.',0),
     45122004 => array('Die Etikettendefinition fÃŒr Windrosenrichtungen mÃŒssen 16 Werte haben (eine fÃŒr jede Kompassrichtung).',0),
     45222005 => array('Der Linientyp fÃŒr radiale Linien muss einer von ("solid","dotted","dashed","longdashed") sein.',0),
     45322006 => array('Es wurde ein ungÃŒltiger Windrosentyp angegeben.',0),
     45422007 => array('Es wurden zu wenig Werte fÃŒr die Bereichslegende angegeben.',0),
    43945522008 => array('Interner Fehler: Versuch, eine freie Windrose zu plotten, obwohl der Typ keine freie Windrose ist.',0),
    44045622009 => array('Du hast die gleiche Richtung zweimal angegeben, einmal mit einem Winkel und einmal mit einer Kompassrichtung (%f Grad).',0),
    44145722010 => array('Die Richtung muss entweder ein numerischer Wert sein oder eine der 16 Kompassrichtungen',0),
    44245822011 => array('Der Windrosenindex muss ein numerischer oder Richtungswert sein. Du hast angegeben Index=%d',1),
    443 22012 => array('Die radiale Achsendefinition für die Windrose enthält eine nicht aktivierte Richtung.',0),
    444 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),
    445 22014 => array('Der Index für eine Kompassrichtung muss zwischen 0 und 15 sein.',0),
     45922012 => array('Die radiale Achsendefinition fÃŒr die Windrose enthÀlt eine nicht aktivierte Richtung.',0),
     46022013 => array('Du hast dasselbe Look&Feel fÃŒr die gleiche Kompassrichtung zweimal engegeben, einmal mit Text und einmal mit einem Index (Index=%d)',1),
     46122014 => array('Der Index fÃŒr eine Kompassrichtung muss zwischen 0 und 15 sein.',0),
    44646222015 => array('Du hast einen unbekannten Windrosenplottyp angegeben.',0),
    44746322016 => array('Der Windrosenarmindex muss ein numerischer oder ein Richtungswert sein.',0),
    44846422017 => array('Die Windrosendaten enthalten eine Richtung, die nicht aktiviert ist. Bitte berichtige, welche Label angezeigt werden sollen.',0),
    449 22018 => array('Du hast für dieselbe Kompassrichtung zweimal Daten angegeben, einmal mit Text und einmal mit einem Index (Index=%d)',1),
    450 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),
    451 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),
     46522018 => array('Du hast fÃŒr dieselbe Kompassrichtung zweimal Daten angegeben, einmal mit Text und einmal mit einem Index (Index=%d)',1),
     46622019 => 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),
     46722020 => 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),
    45246822021 => array('It is only possible to add Text, IconPlot or WindrosePlot to a Windrose Graph',0),
    453469
     
    457473
    45847413001 => array('Unbekannter Nadeltypstil (%d).',1),
    459 13002 => array('Ein Wert für das Odometer (%f) ist außerhalb des angegebenen Bereichs [%f,%f]',3),
     47513002 => array('Ein Wert fÃŒr das Odometer (%f) ist außerhalb des angegebenen Bereichs [%f,%f]',3),
    460476
    461477/*
     
    4654811001 => array('Unbekannte Kodier-Specifikation: %s',1),
    4664821002 => array('datenvalidierung schlug fehl. [%s] kann nicht mittels der Kodierung "%s" kodiert werden',2),
    467 1003 => array('Interner Kodierfehler. Kodieren von %s ist nicht möglich in Code 128',1),
     4831003 => array('Interner Kodierfehler. Kodieren von %s ist nicht möglich in Code 128',1),
    4684841004 => array('Interner barcode Fehler. Unbekannter UPC-E Kodiertyp: %s',1),
    4694851005 => array('Interner Fehler. Das Textzeichen-Tupel (%s, %s) kann nicht im Code-128 Zeichensatz C kodiert werden.',2),
    470 1006 => array('Interner Kodierfehler für CODE 128. Es wurde versucht, CTRL in CHARSET != A zu kodieren.',0),
    471 1007 => array('Interner Kodierfehler für CODE 128. Es wurde versucht, DEL in CHARSET != B zu kodieren.',0),
    472 1008 => array('Interner Kodierfehler für CODE 128. Es wurde versucht, kleine Buchstaben in CHARSET != B zu kodieren.',0),
    473 1009 => array('Kodieren mittels CODE 93 wird noch nicht unterstützt.',0),
    474 1010 => array('Kodieren mittels POSTNET wird noch nicht unterstützt.',0),
    475 1011 => array('Nicht untrstütztes Barcode-Backend für den Typ %s',1),
     4861006 => array('Interner Kodierfehler fÃŒr CODE 128. Es wurde versucht, CTRL in CHARSET != A zu kodieren.',0),
     4871007 => array('Interner Kodierfehler fÃŒr CODE 128. Es wurde versucht, DEL in CHARSET != B zu kodieren.',0),
     4881008 => array('Interner Kodierfehler fÃŒr CODE 128. Es wurde versucht, kleine Buchstaben in CHARSET != B zu kodieren.',0),
     4891009 => array('Kodieren mittels CODE 93 wird noch nicht unterstÃŒtzt.',0),
     4901010 => array('Kodieren mittels POSTNET wird noch nicht unterstÃŒtzt.',0),
     4911011 => array('Nicht untrstÃŒtztes Barcode-Backend fÃŒr den Typ %s',1),
    476492
    477493/*
     
    479495*/
    480496
     49726000 => 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),
    48149826001 => array('PDF417: Die Anzahl der Spalten muss zwischen 1 und 30 sein.',0),
    48249926002 => array('PDF417: Der Fehler-Level muss zwischen 0 und 8 sein.',0),
    483 26003 => array('PDF417: Ungültiges Format für Eingabedaten, um sie mit PDF417 zu kodieren.',0),
    484 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),
    485 26005 => array('PDF417: Die Datei "%s" kann nicht zum Schreiben geöffnet werden.',1),
    486 26006 => array('PDF417: Interner Fehler. Die Eingabedatendatei für PDF417-Cluster %d ist fehlerhaft.',1),
    487 26007 => array('PDF417: Interner Fehler. GetPattern: Ungültiger Code-Wert %d (Zeile %d)',2),
     50026003 => array('PDF417: UngÃŒltiges Format fÃŒr Eingabedaten, um sie mit PDF417 zu kodieren.',0),
     50126004 => 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),
     50226005 => array('PDF417: Die Datei "%s" kann nicht zum Schreiben geöffnet werden.',1),
     50326006 => array('PDF417: Interner Fehler. Die Eingabedatendatei fÃŒr PDF417-Cluster %d ist fehlerhaft.',1),
     50426007 => array('PDF417: Interner Fehler. GetPattern: UngÃŒltiger Code-Wert %d (Zeile %d)',2),
    48850526008 => array('PDF417: Interner Fehler. Modus wurde nicht in der Modusliste!! Modus %d',1),
    489 26009 => array('PDF417: Kodierfehler: Ungültiges Zeichen. Zeichen kann nicht mit ASCII-Code %d kodiert werden.',1),
     50626009 => array('PDF417: Kodierfehler: UngÃŒltiges Zeichen. Zeichen kann nicht mit ASCII-Code %d kodiert werden.',1),
    49050726010 => array('PDF417: Interner Fehler: Keine Eingabedaten beim Dekodieren.',0),
    491 26011 => array('PDF417: Kodierfehler. Numerisches Kodieren bei nicht-numerischen Daten nicht möglich.',0),
    492 26012 => array('PDF417: Interner Fehler. Es wurden für den Binary-Kompressor keine Daten zum Dekodieren eingegeben.',0),
     50826011 => array('PDF417: Kodierfehler. Numerisches Kodieren bei nicht-numerischen Daten nicht möglich.',0),
     50926012 => array('PDF417: Interner Fehler. Es wurden fÃŒr den Binary-Kompressor keine Daten zum Dekodieren eingegeben.',0),
    49351026013 => array('PDF417: Interner Fehler. Checksum Fehler. Koeffiziententabellen sind fehlerhaft.',0),
    494 26014 => array('PDF417: Interner Fehler. Es wurden keine Daten zum Berechnen von Kodewörtern eingegeben.',0),
    495 26015 => array('PDF417: Interner Fehler. Ein Eintrag 0 in die Statusübertragungstabellen ist nicht NULL. Eintrag 1 = (%s)',1),
    496 26016 => array('PDF417: Interner Fehler: Nichtregistrierter Statusübertragungsmodus beim Dekodieren.',0),
     51126014 => array('PDF417: Interner Fehler. Es wurden keine Daten zum Berechnen von Kodewörtern eingegeben.',0),
     51226015 => array('PDF417: Interner Fehler. Ein Eintrag 0 in die StatusÃŒbertragungstabellen ist nicht NULL. Eintrag 1 = (%s)',1),
     51326016 => array('PDF417: Interner Fehler: Nichtregistrierter StatusÃŒbertragungsmodus beim Dekodieren.',0),
     514
     515
     516/*
     517** jpgraph_contour
     518*/
     519
     52028001 => array('Dritten parameter fur Contour muss ein vector der fargen sind.',0),
     52128002 => array('Die anzahlen der farges jeder isobar linien muss gleich sein.',0),
     52228003 => array('ContourPlot Interner Fehler: isobarHCrossing: Spalten index ist zu hoch (%d)',1),
     52328004 => array('ContourPlot Interner Fehler: isobarHCrossing: Reihe index ist zu hoch (%d)',1),
     52428005 => array('ContourPlot Interner Fehler: isobarVCrossing: Reihe index ist zu hoch (%d)',1),
     52528006 => array('ContourPlot Interner Fehler: isobarVCrossing: Spalten index ist zu hoch (%d)',1),
     52628007 => array('ContourPlot. Interpolation faktor ist zu hoch (>5)',0),
     527
     528
     529/*
     530 * jpgraph_matrix and colormap
     531*/
     53229201 => array('Min range value must be less or equal to max range value for colormaps',0),
     53329202 => array('The distance between min and max value is too small for numerical precision',0),
     53429203 => array('Number of color quantification level must be at least %d',1),
     53529204 => array('Number of colors (%d) is invalid for this colormap. It must be a number that can be written as: %d + k*%d',3),
     53629205 => array('Colormap specification out of range. Must be an integer in range [0,%d]',1),
     53729206 => array('Invalid object added to MatrixGraph',0),
     53829207 => array('Empty input data specified for MatrixPlot',0),
     53929208 => array('Unknown side specifiction for matrix labels "%s"',1),
     54029209 => array('CSIM Target matrix must be the same size as the data matrix (csim=%d x %d, data=%d x %d)',4),
     54129210 => 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*/
     54730001 => array("Theme::%s() is not defined. \nPlease make %s(\$graph) function in your theme classs.",2),
    497548
    498549
  • trunk/client/modules/Elezioni/grafici/lang/en.inc.php

    r267 r284  
    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 1017 2008-07-08 06:09:28Z ljp $
     5// Created:     2006-01-25
     6// Ver:        $Id: en.inc.php 1886 2009-10-01 23:30:16Z ljp $
    77//
    8 // Copyright (c) Aditus Consulting. All rights reserved.
     8// Copyright (c) Asial Corporation. 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),
     1056033 => array('Array of fonts must contain arrays with 3 elements, i.e. (Family, Style, Size)',0),
    105106
    106107/*
     
    18718815010 => array('Sum of all data is 0 for Pie.',0),
    18818915011 => array('In order to use image transformation you must include the file jpgraph_imgtrans.php in your script.',0),
     19015012 => array('PiePlot::SetTheme() is no longer supported. Use PieGraph::SetTheme()',0),
    189191
    190192/*
     
    25725924002 => array('FuncGenerator : Syntax error in function specification ',0),
    25826024003 => array('DateScaleUtils: Unknown tick type specified in call to GetTicks()',0),
     26124004 => array('ReadCSV2: Column count mismatch in %s line %d',2),
    259262/*
    260263**  jpgraph
     
    272275
    27327625010 => array('Graph::Add() You tried to add a null plot to the graph.',0),
    274 25011 => array('Graph::AddY2() You tried to add a null plot to the graph.',0), 
    275 25012 => array('Graph::AddYN() You tried to add a null plot to the graph.',0), 
     27725011 => array('Graph::AddY2() You tried to add a null plot to the graph.',0),
     27825012 => array('Graph::AddYN() You tried to add a null plot to the graph.',0),
    27627925013 => array('You can only add standard plots to multiple Y-axis',0),
    277 25014 => array('Graph::AddText() You tried to add a null text to the graph.',0), 
    278 25015 => array('Graph::AddLine() You tried to add a null line to the graph.',0), 
     28025014 => array('Graph::AddText() You tried to add a null text to the graph.',0),
     28125015 => array('Graph::AddLine() You tried to add a null line to the graph.',0),
    27928225016 => array('Graph::AddBand() You tried to add a null band to the graph.',0),
    28028325017 => 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),
     
    30230525037 => array('The image format of your background image (%s) is not supported in your system configuration. ',1),
    30330625038 => array('Background image seems to be of different type (has different file extension) than specified imagetype. Specified: %s File: %s',2),
    304 25039 => array('Can\'t read background image: "%s"',1), 
     30725039 => array('Can\'t read background image: "%s"',1),
    305308
    30630925040 => array('It is not possible to specify both a background image and a background country flag.',0),
     
    32232525055 => array('Axis::SetTickDirection() is deprecated. Use Axis::SetTickSide() instead',0),
    32332625056 => array('SetTickLabelMargin() is deprecated. Use Axis::SetLabelMargin() instead.',0),
    324 25057 => array('SetTextTicks() is deprecated. Use SetTextTickInterval() instead.',0), 
     32725057 => array('SetTextTicks() is deprecated. Use SetTextTickInterval() instead.',0),
    32532825058 => array('Text label interval must be specified >= 1.',0),
    32632925059 => array('SetLabelPos() is deprecated. Use Axis::SetLabelSide() instead.',0),
     
    36636925097 => array('Color specified as empty string in PushColor().',0),
    36737025098 => array('Negative Color stack index. Unmatched call to PopColor()',0),
    368 25099 => array('Parameters for brightness and Contrast out of range [-1,1]',0), 
     37125099 => array('Parameters for brightness and Contrast out of range [-1,1]',0),
    369372
    37037325100 => 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),
     
    38538825114 => 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),
    38638925115 => array('Can\'t set permission for cached image "%s". Permission problem?',1),
    387 25116 => array('Cant open file from cache "%s"',1), 
     39025116 => array('Cant open file from cache "%s"',1),
    38839125117 => array('Can\'t open cached image "%s" for reading.',1),
    38939225118 => array('Can\'t create directory "%s". Make sure PHP has write permission to this directory.',1),
     
    40040325128 => 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),
    40140425129 => array('Anti-alias can not be used with dashed lines. Please disable anti-alias or use solid lines.',0),
    402 
     40525130 => 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
     40725131 => array('StrokeBoxedText2() only supports TTF fonts and not built-in bitmap fonts.',0),
     40825132 => array('Undefined property %s.',1),
     40925133 => array('Use Graph::SetTheme() after Graph::SetScale().',0),
     410
     411/*
     412**  jpgraph_led
     413*/
     414
     41525500 => 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),
    403416
    404417/*
     
    409422
    410423/*
    411 **  jpgraph_table 
     424**  jpgraph_table
    412425*/
    413426
     
    478491** PDF417
    479492*/
    480 
     49326000 => 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),
    48149426001 => array('PDF417: Number of Columns must be >= 1 and <= 30',0),
    48249526002 => array('PDF417: Error level must be between 0 and 8',0),
     
    49650926016 => array('PDF417: Internal error: Unrecognized state transition mode in decode.',0),
    497510
     511/*
     512** jpgraph_contour
     513*/
     514
     51528001 => array('Third argument to Contour must be an array of colors.',0),
     51628002 => array('Number of colors must equal the number of isobar lines specified',0),
     51728003 => array('ContourPlot Internal Error: isobarHCrossing: Coloumn index too large (%d)',1),
     51828004 => array('ContourPlot Internal Error: isobarHCrossing: Row index too large (%d)',1),
     51928005 => array('ContourPlot Internal Error: isobarVCrossing: Row index too large (%d)',1),
     52028006 => array('ContourPlot Internal Error: isobarVCrossing: Col index too large (%d)',1),
     52128007 => array('ContourPlot interpolation factor is too large (>5)',0),
     522
     523/*
     524 * jpgraph_matrix and colormap
     525*/
     52629201 => array('Min range value must be less or equal to max range value for colormaps',0),
     52729202 => array('The distance between min and max value is too small for numerical precision',0),
     52829203 => array('Number of color quantification level must be at least %d',1),
     52929204 => array('Number of colors (%d) is invalid for this colormap. It must be a number that can be written as: %d + k*%d',3),
     53029205 => array('Colormap specification out of range. Must be an integer in range [0,%d]',1),
     53129206 => array('Invalid object added to MatrixGraph',0),
     53229207 => array('Empty input data specified for MatrixPlot',0),
     53329208 => array('Unknown side specifiction for matrix labels "%s"',1),
     53429209 => array('CSIM Target matrix must be the same size as the data matrix (csim=%d x %d, data=%d x %d)',4),
     53529210 => 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*/
     54130001 => array("Theme::%s() is not defined. \nPlease make %s(\$graph) function in your theme classs.",2),
    498542
    499543);
  • trunk/client/modules/Elezioni/grafici/lang/prod.inc.php

    r267 r284  
    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 993 2008-03-30 21:17:41Z ljp $
     7// Ver:         $Id: prod.inc.php 1886 2009-10-01 23:30:16Z ljp $
    88//
    9 // Copyright (c) Aditus Consulting. All rights reserved.
     9// Copyright (c) Asial Corporation. 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),
     786033 => array(DEFAULT_ERROR_MESSAGE.'6033',0),
    78797001 => array(DEFAULT_ERROR_MESSAGE.'7001',0),
    79808001 => array(DEFAULT_ERROR_MESSAGE.'8001',0),
     
    12012115010 => array(DEFAULT_ERROR_MESSAGE.'15010',0),
    12112215011 => array(DEFAULT_ERROR_MESSAGE.'15011',0),
     12315012 => array(DEFAULT_ERROR_MESSAGE.'15012',0),
    12212416001 => array(DEFAULT_ERROR_MESSAGE.'16001',0),
    12312516002 => array(DEFAULT_ERROR_MESSAGE.'16002',0),
     
    14815024002 => array(DEFAULT_ERROR_MESSAGE.'24002',0),
    14915124003 => array(DEFAULT_ERROR_MESSAGE.'24003',0),
     15224004 => array(DEFAULT_ERROR_MESSAGE.'24004',0),
    15015325001 => array(DEFAULT_ERROR_MESSAGE.'25001',0),
    15115425002 => array(DEFAULT_ERROR_MESSAGE.'25002',0),
     
    27627925128 => array(DEFAULT_ERROR_MESSAGE.'25128',0),
    27728025129 => array(DEFAULT_ERROR_MESSAGE.'25129',0),
     28125130 => array(DEFAULT_ERROR_MESSAGE.'25130',0),
     28225131 => array(DEFAULT_ERROR_MESSAGE.'25131',0),
     28325132 => array(DEFAULT_ERROR_MESSAGE.'25132',0),
     28425133 => array(DEFAULT_ERROR_MESSAGE.'25133',0),
     28525500 => array(DEFAULT_ERROR_MESSAGE.'25500',0),
    27828624003 => array(DEFAULT_ERROR_MESSAGE.'24003',0),
    27928724004 => array(DEFAULT_ERROR_MESSAGE.'24004',0),
     
    3213291010 => array(DEFAULT_ERROR_MESSAGE.'1010',0),
    3223301011 => array(DEFAULT_ERROR_MESSAGE.'1011',0),
     33126000 => array(DEFAULT_ERROR_MESSAGE.'26000',0),
    32333226001 => array(DEFAULT_ERROR_MESSAGE.'26001',0),
    32433326002 => array(DEFAULT_ERROR_MESSAGE.'26002',0),
     
    35336227014 => array(DEFAULT_ERROR_MESSAGE.'27014',0),
    35436327015 => array(DEFAULT_ERROR_MESSAGE.'27015',0),
     364
     36528001 => array(DEFAULT_ERROR_MESSAGE.'28001',0),
     36628002 => array(DEFAULT_ERROR_MESSAGE.'28002',0),
     36728003 => array(DEFAULT_ERROR_MESSAGE.'28003',0),
     36828004 => array(DEFAULT_ERROR_MESSAGE.'28004',0),
     36928005 => array(DEFAULT_ERROR_MESSAGE.'28005',0),
     37028006 => array(DEFAULT_ERROR_MESSAGE.'28006',0),
     37128007 => array(DEFAULT_ERROR_MESSAGE.'28007',0),
     372
     37329201 => array(DEFAULT_ERROR_MESSAGE.'28001',0),
     37429202 => array(DEFAULT_ERROR_MESSAGE.'28002',0),
     37529203 => array(DEFAULT_ERROR_MESSAGE.'28003',0),
     37629204 => array(DEFAULT_ERROR_MESSAGE.'28004',0),
     37729205 => array(DEFAULT_ERROR_MESSAGE.'28005',0),
     37829206 => array(DEFAULT_ERROR_MESSAGE.'28006',0),
     37929207 => array(DEFAULT_ERROR_MESSAGE.'28007',0),
     38029208 => array(DEFAULT_ERROR_MESSAGE.'28008',0),
     38129209 => array(DEFAULT_ERROR_MESSAGE.'28009',0),
     38229210 => array(DEFAULT_ERROR_MESSAGE.'28010',0),
     383
    355384);
    356385
  • trunk/client/temi/spectral/index.php

    r282 r284  
    156156        if($resblk->rowCount()){
    157157               
    158                 while ($row = mysql_fetch_array($resblk)) {
     158                while ($row = $resblk->fetch(PDO::FETCH_BOTH)) {
    159159                        $id_w=$row['id'];
    160160                        $nome=$row['nome_file'];
Note: See TracChangeset for help on using the changeset viewer.